From tismer at codespeak.net Mon May 1 06:09:35 2006 From: tismer at codespeak.net (tismer at codespeak.net) Date: Mon, 1 May 2006 06:09:35 +0200 (CEST) Subject: [pypy-svn] r26627 - pypy/extradoc/soc-2006 Message-ID: <20060501040935.6240310098@code0.codespeak.net> Author: tismer Date: Mon May 1 06:09:31 2006 New Revision: 26627 Modified: pypy/extradoc/soc-2006/planning.txt Log: applied as a PSF mentor. acceptance pending Modified: pypy/extradoc/soc-2006/planning.txt ============================================================================== --- pypy/extradoc/soc-2006/planning.txt (original) +++ pypy/extradoc/soc-2006/planning.txt Mon May 1 06:09:31 2006 @@ -16,6 +16,7 @@ Aurelien Campeas (pending) Samuele Pedroni Armin Rigo +Christian Tismer (pending) On the 27th of April or so, mwh will send a list of all not-yet-registered mentors to Neal Norwitz. From tismer at codespeak.net Mon May 1 06:48:39 2006 From: tismer at codespeak.net (tismer at codespeak.net) Date: Mon, 1 May 2006 06:48:39 +0200 (CEST) Subject: [pypy-svn] r26628 - pypy/dist/pypy/doc/discussion Message-ID: <20060501044839.4C3D010098@code0.codespeak.net> Author: tismer Date: Mon May 1 06:48:33 2006 New Revision: 26628 Modified: pypy/dist/pypy/doc/discussion/howtoimplementpickling.txt Log: partial check-in, just to show that I'm at it :-) Modified: pypy/dist/pypy/doc/discussion/howtoimplementpickling.txt ============================================================================== --- pypy/dist/pypy/doc/discussion/howtoimplementpickling.txt (original) +++ pypy/dist/pypy/doc/discussion/howtoimplementpickling.txt Mon May 1 06:48:33 2006 @@ -1,5 +1,5 @@ -Designing thread pickling -------------------------- +Designing thread pickling or "the Essence of Stackless Python" +-------------------------------------------------------------- Thread pickling is a unique feature in Stackless Python and should be implemented for PyPy pretty soon. @@ -116,3 +116,39 @@ Unfortunately this is not even possible with SLP, because there are different flavors of state which make it hard to go without extra information. + +Analogies between SLP and PyPy +.............................. + +SLP has undergone several rewrites. The first implemenation was aiming +at complete collaboration. A new frame's execution was deferred until +all the preparational C function calls had left the C stack. There +was no extra state to be saved. + +Well, this is only partially true - there are a couple of situations +where a recursive call could not be avoided, since the necessary support +would require heave rewriting of the implementation. +Examples are + +- map is a stateful implementation of iterating over a sequence + of operations. It can be made non-recursive if the map operation + creates its own frame to keep state. + +- __init__ looks trivial, but the semantics is that the return value + of __init__ is supposed to be None, and CPy has a special check for this + after the call. This might simply be ignored, but it is a simple example + for a case that cannot be hadnled automatically. + +- things like operator.__add__ can theoretically generate a wild pattern + of recursive calls while CPy tries to figure out if it is a numeric + add or a sequence add, and other callbacks may occur when methods + like __coerce__ get involved. + +The second implementation took a radically different approach. Context +switches were done by hijacking parts of the C stack, storing them +away and replacing them by the stack fragment that the target needs. +This is very powerful and allows to switch even in the context of +foreign code. With a little risk, I was even able to add concurrency +to foreign Fortran code. + +The above concept is called Hard switchind, the collaborative Soft switching. \ No newline at end of file From tismer at codespeak.net Mon May 1 07:07:41 2006 From: tismer at codespeak.net (tismer at codespeak.net) Date: Mon, 1 May 2006 07:07:41 +0200 (CEST) Subject: [pypy-svn] r26629 - pypy/dist/pypy/doc/discussion Message-ID: <20060501050741.7F9D9100A7@code0.codespeak.net> Author: tismer Date: Mon May 1 07:07:38 2006 New Revision: 26629 Modified: pypy/dist/pypy/doc/discussion/howtoimplementpickling.txt Log: yes another temporary - stop me now if you think this is nonsense Modified: pypy/dist/pypy/doc/discussion/howtoimplementpickling.txt ============================================================================== --- pypy/dist/pypy/doc/discussion/howtoimplementpickling.txt (original) +++ pypy/dist/pypy/doc/discussion/howtoimplementpickling.txt Mon May 1 07:07:38 2006 @@ -117,8 +117,8 @@ there are different flavors of state which make it hard to go without extra information. -Analogies between SLP and PyPy -.............................. +SLP switching strategies +........................ SLP has undergone several rewrites. The first implemenation was aiming at complete collaboration. A new frame's execution was deferred until @@ -151,4 +151,29 @@ foreign code. With a little risk, I was even able to add concurrency to foreign Fortran code. -The above concept is called Hard switchind, the collaborative Soft switching. \ No newline at end of file +The above concept is called Hard switching, the collaborative Soft switching. +Note that an improved version of Hard is still the building block +for greenlets, which makes them not really green - I'd name it yellow. + +The latest SLP rewrite combines both ideas, trying to use Soft whenever +possible, but using Hard when nested interpreters are in the way. + +Notabene, it was never tried to pickle tasklets when Hard +was involved. In SLP, pickling works with Soft. To gather more +pickleable situations, you need to invent new frame types +or write replacement Python code and switch it Soft. + +Analogies between SLP and PyPy +.............................. + +Right now, PyPy saves C state of functions in tiny activation records. +This is an improvement over storing raw stack slices, but the pattern +is similar: The C stack state gets restored when we switch. + +In this sense, it was the astonishing resume when Richard and I discussed +this: PyPy essentially does a variant of Hard switching! At least it +does a compromize that does not really help with pickling. + +Ways to handle the problem in a minimalistic way +................................................ + From tismer at codespeak.net Mon May 1 08:26:02 2006 From: tismer at codespeak.net (tismer at codespeak.net) Date: Mon, 1 May 2006 08:26:02 +0200 (CEST) Subject: [pypy-svn] r26630 - pypy/dist/pypy/doc/discussion Message-ID: <20060501062602.0EF37100A0@code0.codespeak.net> Author: tismer Date: Mon May 1 08:25:59 2006 New Revision: 26630 Modified: pypy/dist/pypy/doc/discussion/howtoimplementpickling.txt Log: I think this is it, although the text could need a redesign. In a sense, this contains all what Stackless is about, and a bit more. Modified: pypy/dist/pypy/doc/discussion/howtoimplementpickling.txt ============================================================================== --- pypy/dist/pypy/doc/discussion/howtoimplementpickling.txt (original) +++ pypy/dist/pypy/doc/discussion/howtoimplementpickling.txt Mon May 1 08:25:59 2006 @@ -174,6 +174,101 @@ this: PyPy essentially does a variant of Hard switching! At least it does a compromize that does not really help with pickling. +On the other had, this approach is half the way. It turns out to +be an improvement over SLP not to have to avoid recursions in the +first place. Instead, it seems to be even more elegant and efficient +to get rid of unnecessary state right in the context of a switch! + Ways to handle the problem in a minimalistic way ................................................ +Comparing the different approaches of SLP and PyPy, it appears to be +not necessary to change the interpreter in the first place. PyPy does +not need to change its calling behavior in order t be cooperative. +The key point is to find out which activation records need to +be stored at all. This should be possible to identify as a part +of the stackless transform. + +Consider the simple most common case of calling a normal Python function. +There are several calls to functions involved, which do preparational +steps. Without trying to be exact (this is part of the work to be done), +involved steps are + +- decode the arguments of the function + +- prepare a new frame + +- store the arguments in the frame + +- execute the frame + +- return the result + +Now assume that we do not execute the frame, but do a context switch instead, +then a sequence of activation records is stored on the heap. +If we want to re-activate this chain of activation records, what do +we really need to do the function call? + +- the argument decoding is done, already, and the fact that we could have done + the function call shows, that no exception ocoured. We can ignore the rest + this activation record and do the housekeeping. + +- the frame is prepared, and arguments are stored in it. The operation + succeeded, and we have the frame. We can ignore exception handling + and just do housekeeping by getting rid of references. + +- for executing the frame, we need a special function that executes frames. It + is possible that we need different flavors due to contexts. SLP does this + by using different registered functions which operate on a frame, depending + on the frame's state (first entry, reentry after call, returning etc) + +- after executing the frame, exceptions need to be handled in the usual way, + and we should return to the issuer of the call. + +Some deeper analysis is needed to get these things correct. +But is should have become quite clear, that after all the preparational +things have been done, there is no other state necessary than what we +have in the Python frames: bound arguments, instruction pointer, that's it. + +My proposal is now to do such an analysis by hand, identify the different +cases to be handled, and then trying to find an algorithm that automatically +identifies the blocks in the whole program, where the restoring of the +C stack can be avoided, and we can jump back to the caller, directly. + +A rough sketch of the necessary analysis: + +for every block in an RPython function that can reach unwind: +Analyse control flow. It should be immediately leading to +the return block with only one output variable. All other alive variables +should have ended their liveness in this block. + +I think this will not work in the first place. For the bound frame +arguments for instance, I think we need some notation that these are +held by the frame, and we can drop their liveness before doing the call, +hence we don't need to save these variables in the activation record, +and hence the whole activation record can be removed. + +As a conclusion of this incomplete first analysis, it seems to be necessary +to identify useless activation records in order to support pickling. +The remaining, irreducible activation records should then be those +which hold a reference to a Python frame. +Such a chain is pickleable if its root points back to the context switching code +of the interp-level implementation of coroutines. + +As an observation, this transform not only enables pickling, but +also is an optimization, if we can save to save many activation records. + +Another possible observation which I hope to be able to prove is this: +The remaining irreducible activation records which don't just hold +a Python frame are those which should be considered special. +They should be turned into something like special frames, and they would +be the key to make PyPy completely stackless, a goal which is practically +impossible for SLP! These activation records would need to become +part of the official interface and need to get naming support for +their necessary functions. + +I wish to stop this paper here. I believe everything else +needs to be tried in an implementation, and this is so far +all I can do just with imagination. + +best - chris From tismer at codespeak.net Mon May 1 09:29:46 2006 From: tismer at codespeak.net (tismer at codespeak.net) Date: Mon, 1 May 2006 09:29:46 +0200 (CEST) Subject: [pypy-svn] r26631 - pypy/dist/pypy/doc/discussion Message-ID: <20060501072946.51EFE100A0@code0.codespeak.net> Author: tismer Date: Mon May 1 09:29:43 2006 New Revision: 26631 Modified: pypy/dist/pypy/doc/discussion/howtoimplementpickling.txt Log: some refinements Modified: pypy/dist/pypy/doc/discussion/howtoimplementpickling.txt ============================================================================== --- pypy/dist/pypy/doc/discussion/howtoimplementpickling.txt (original) +++ pypy/dist/pypy/doc/discussion/howtoimplementpickling.txt Mon May 1 09:29:43 2006 @@ -64,7 +64,7 @@ prickelpit.c file. It should be simple and straightforward to redo these implementations. -Nevertheless there is a complication. The most natural to support +Nevertheless there is a complication. The most natural way to support pickling is providing a __getstate__/__setstate__ method pair. This is ok for extension types like coroutines/tasklets, but not allowed to use for existing types, since adding new methods @@ -137,12 +137,13 @@ - __init__ looks trivial, but the semantics is that the return value of __init__ is supposed to be None, and CPy has a special check for this after the call. This might simply be ignored, but it is a simple example - for a case that cannot be hadnled automatically. + for a case that cannot be handled automatically. - things like operator.__add__ can theoretically generate a wild pattern of recursive calls while CPy tries to figure out if it is a numeric add or a sequence add, and other callbacks may occur when methods - like __coerce__ get involved. + like __coerce__ get involved. This will never be solved for SLP, but + might get a solution by the strategy outlined below. The second implementation took a radically different approach. Context switches were done by hijacking parts of the C stack, storing them @@ -151,11 +152,11 @@ foreign code. With a little risk, I was even able to add concurrency to foreign Fortran code. -The above concept is called Hard switching, the collaborative Soft switching. +The above concept is called Hard (switching), the collaborative Soft (switching). Note that an improved version of Hard is still the building block for greenlets, which makes them not really green - I'd name it yellow. -The latest SLP rewrite combines both ideas, trying to use Soft whenever +The latest SLP rewrites combine both ideas, trying to use Soft whenever possible, but using Hard when nested interpreters are in the way. Notabene, it was never tried to pickle tasklets when Hard @@ -171,10 +172,10 @@ is similar: The C stack state gets restored when we switch. In this sense, it was the astonishing resume when Richard and I discussed -this: PyPy essentially does a variant of Hard switching! At least it +this last week: PyPy essentially does a variant of Hard switching! At least it does a compromize that does not really help with pickling. -On the other had, this approach is half the way. It turns out to +On the other hand, this approach is half the way. It turns out to be an improvement over SLP not to have to avoid recursions in the first place. Instead, it seems to be even more elegant and efficient to get rid of unnecessary state right in the context of a switch! @@ -184,7 +185,7 @@ Comparing the different approaches of SLP and PyPy, it appears to be not necessary to change the interpreter in the first place. PyPy does -not need to change its calling behavior in order t be cooperative. +not need to change its calling behavior in order to be cooperative. The key point is to find out which activation records need to be stored at all. This should be possible to identify as a part of the stackless transform. @@ -205,13 +206,13 @@ - return the result Now assume that we do not execute the frame, but do a context switch instead, -then a sequence of activation records is stored on the heap. +then right now a sequence of activation records is stored on the heap. If we want to re-activate this chain of activation records, what do -we really need to do the function call? +we really need befor we can do the function call? - the argument decoding is done, already, and the fact that we could have done - the function call shows, that no exception ocoured. We can ignore the rest - this activation record and do the housekeeping. + the function call shows, that no exception occured. We can ignore the rest + of this activation record and do the housekeeping. - the frame is prepared, and arguments are stored in it. The operation succeeded, and we have the frame. We can ignore exception handling @@ -220,20 +221,20 @@ - for executing the frame, we need a special function that executes frames. It is possible that we need different flavors due to contexts. SLP does this by using different registered functions which operate on a frame, depending - on the frame's state (first entry, reentry after call, returning etc) + on the frame's state (first entry, reentry after call, returning, yielding etc) - after executing the frame, exceptions need to be handled in the usual way, and we should return to the issuer of the call. Some deeper analysis is needed to get these things correct. But is should have become quite clear, that after all the preparational -things have been done, there is no other state necessary than what we +steps have been done, there is no other state necessary than what we have in the Python frames: bound arguments, instruction pointer, that's it. My proposal is now to do such an analysis by hand, identify the different cases to be handled, and then trying to find an algorithm that automatically identifies the blocks in the whole program, where the restoring of the -C stack can be avoided, and we can jump back to the caller, directly. +C stack can be avoided, and we can jump back to the previous caller, directly. A rough sketch of the necessary analysis: @@ -252,7 +253,7 @@ to identify useless activation records in order to support pickling. The remaining, irreducible activation records should then be those which hold a reference to a Python frame. -Such a chain is pickleable if its root points back to the context switching code +Such a chain is pickleable iff its root points back to the context switching code of the interp-level implementation of coroutines. As an observation, this transform not only enables pickling, but From tismer at codespeak.net Mon May 1 10:33:31 2006 From: tismer at codespeak.net (tismer at codespeak.net) Date: Mon, 1 May 2006 10:33:31 +0200 (CEST) Subject: [pypy-svn] r26632 - pypy/dist/pypy/doc/discussion Message-ID: <20060501083331.BB12D10098@code0.codespeak.net> Author: tismer Date: Mon May 1 10:33:29 2006 New Revision: 26632 Modified: pypy/dist/pypy/doc/discussion/howtoimplementpickling.txt Log: added a conclusion which was stunning for me. But I think it is a very good one, improving the wholeproject if we can solve it. Modified: pypy/dist/pypy/doc/discussion/howtoimplementpickling.txt ============================================================================== --- pypy/dist/pypy/doc/discussion/howtoimplementpickling.txt (original) +++ pypy/dist/pypy/doc/discussion/howtoimplementpickling.txt Mon May 1 10:33:29 2006 @@ -273,3 +273,41 @@ all I can do just with imagination. best - chris + +Just an addition after some more thinking +......................................... + +Actually it struck me after checking this in, that the problem of +determining which blocks need to save state and which not it not +really a Stackless problem. It is a system-immanent problem +of a missing optimization that we still did not try to solve. + +Speaking in terms of GC transform, and especially the refcounting, +it is probably easy to understand what I mean. Our current refcounting +implementation is naive, in the sense that we donot try to do the +optimizations which every extension writer does by hand: +We do not try to save references. + +This is also why I'm always arguing that refcounting can be and +effectively *is* efficient, because CPythob does it very well. + +Our refcounting is not aware of variable lifeness, it does not +track references which are known to be held by other objects. +Optimizing that would do two things: The refcounting would become +very efficient, since we would save som 80 % of it. +THe second part, which is relevant to the pickling problem is this: +By doing a proper analysis, we already would have lost references to +all the variables which we don't need to save any longer, because +we know that they are held in, for instance, frames. + +I hope you understand that: If we improve the life-time analysis +of veriables, the sketched problem of above about which blocks +need to save state and which don't, should become trivial and should +just vanish. + +Doing this correctly will solve the pickling problem quasi +automatically, leading to a more efficient implementation at the same time. + +I can hear you yelling at me in advance, but it is the truth. + +ciao - chris From nik at codespeak.net Mon May 1 12:51:22 2006 From: nik at codespeak.net (nik at codespeak.net) Date: Mon, 1 May 2006 12:51:22 +0200 (CEST) Subject: [pypy-svn] r26633 - pypy/dist/pypy/rpython/test Message-ID: <20060501105122.70FBD100B5@code0.codespeak.net> Author: nik Date: Mon May 1 12:50:59 2006 New Revision: 26633 Modified: pypy/dist/pypy/rpython/test/test_rlist.py pypy/dist/pypy/rpython/test/test_rtuple.py Log: skip more tests that fail now because of incomplete string support in ootypesystem. 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 May 1 12:50:59 2006 @@ -622,6 +622,7 @@ def test_list_comparestr(self): + self._skip_oo('strings') def fn(i, j, neg=False): s1 = [["hell"], ["hello", "world"]] s1[0][0] += "o" # ensure no interning @@ -700,6 +701,7 @@ def test_not_a_char_list_after_all(self): + self._skip_oo('strings') def fn(): l = ['h', 'e', 'l', 'l', 'o'] return 'world' in l 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 Mon May 1 12:50:59 2006 @@ -88,6 +88,8 @@ assert res is False def test_conv(self): + if self.type_system == "ootype": + py.test.skip("fix me if ootypes supports strings") def t0(): return (3, 2, None) def t1(): From tismer at codespeak.net Mon May 1 21:38:14 2006 From: tismer at codespeak.net (tismer at codespeak.net) Date: Mon, 1 May 2006 21:38:14 +0200 (CEST) Subject: [pypy-svn] r26639 - pypy/dist/pypy/doc/discussion Message-ID: <20060501193814.3DE8810074@code0.codespeak.net> Author: tismer Date: Mon May 1 21:38:12 2006 New Revision: 26639 Modified: pypy/dist/pypy/doc/discussion/howtoimplementpickling.txt Log: some small typos, additions and changes to wording Modified: pypy/dist/pypy/doc/discussion/howtoimplementpickling.txt ============================================================================== --- pypy/dist/pypy/doc/discussion/howtoimplementpickling.txt (original) +++ pypy/dist/pypy/doc/discussion/howtoimplementpickling.txt Mon May 1 21:38:12 2006 @@ -127,7 +127,8 @@ Well, this is only partially true - there are a couple of situations where a recursive call could not be avoided, since the necessary support -would require heave rewriting of the implementation. +would require heavy rewriting of the implementation. + Examples are - map is a stateful implementation of iterating over a sequence @@ -162,12 +163,14 @@ Notabene, it was never tried to pickle tasklets when Hard was involved. In SLP, pickling works with Soft. To gather more pickleable situations, you need to invent new frame types -or write replacement Python code and switch it Soft. +or write replacement Python code and switch it using Soft. Analogies between SLP and PyPy .............................. -Right now, PyPy saves C state of functions in tiny activation records. +Right now, PyPy saves C state of functions in tiny activation records: +the alive variables of a block, together with the entry point of +the function tnat was left. This is an improvement over storing raw stack slices, but the pattern is similar: The C stack state gets restored when we switch. @@ -178,7 +181,8 @@ On the other hand, this approach is half the way. It turns out to be an improvement over SLP not to have to avoid recursions in the first place. Instead, it seems to be even more elegant and efficient -to get rid of unnecessary state right in the context of a switch! +to get rid of unnecessary state right in the context of a switch +and no earlier! Ways to handle the problem in a minimalistic way ................................................ @@ -208,7 +212,7 @@ Now assume that we do not execute the frame, but do a context switch instead, then right now a sequence of activation records is stored on the heap. If we want to re-activate this chain of activation records, what do -we really need befor we can do the function call? +we really need to restore before we can do the function call? - the argument decoding is done, already, and the fact that we could have done the function call shows, that no exception occured. We can ignore the rest @@ -227,7 +231,7 @@ and we should return to the issuer of the call. Some deeper analysis is needed to get these things correct. -But is should have become quite clear, that after all the preparational +But it should have become quite clear, that after all the preparational steps have been done, there is no other state necessary than what we have in the Python frames: bound arguments, instruction pointer, that's it. @@ -257,7 +261,7 @@ of the interp-level implementation of coroutines. As an observation, this transform not only enables pickling, but -also is an optimization, if we can save to save many activation records. +also is an optimization, if we can avoid saving many activation records. Another possible observation which I hope to be able to prove is this: The remaining irreducible activation records which don't just hold @@ -284,18 +288,18 @@ Speaking in terms of GC transform, and especially the refcounting, it is probably easy to understand what I mean. Our current refcounting -implementation is naive, in the sense that we donot try to do the +implementation is naive, in the sense that we do not try to do the optimizations which every extension writer does by hand: We do not try to save references. This is also why I'm always arguing that refcounting can be and -effectively *is* efficient, because CPythob does it very well. +effectively *is* efficient, because CPython does it very well. Our refcounting is not aware of variable lifeness, it does not track references which are known to be held by other objects. Optimizing that would do two things: The refcounting would become -very efficient, since we would save som 80 % of it. -THe second part, which is relevant to the pickling problem is this: +very efficient, since we would save some 80 % of it. +The second part, which is relevant to the pickling problem is this: By doing a proper analysis, we already would have lost references to all the variables which we don't need to save any longer, because we know that they are held in, for instance, frames. @@ -303,11 +307,9 @@ I hope you understand that: If we improve the life-time analysis of veriables, the sketched problem of above about which blocks need to save state and which don't, should become trivial and should -just vanish. - -Doing this correctly will solve the pickling problem quasi +just vanish. Doing this correctly will solve the pickling problem quasi automatically, leading to a more efficient implementation at the same time. -I can hear you yelling at me in advance, but it is the truth. +I hope I told the truth and will try to prove it. ciao - chris From bea at codespeak.net Tue May 2 06:45:51 2006 From: bea at codespeak.net (bea at codespeak.net) Date: Tue, 2 May 2006 06:45:51 +0200 (CEST) Subject: [pypy-svn] r26642 - pypy/extradoc/talk/agile2006 Message-ID: <20060502044551.C575810088@code0.codespeak.net> Author: bea Date: Tue May 2 06:45:49 2006 New Revision: 26642 Modified: pypy/extradoc/talk/agile2006/draftpaper_agile2006.txt Log: final draft Modified: pypy/extradoc/talk/agile2006/draftpaper_agile2006.txt ============================================================================== --- pypy/extradoc/talk/agile2006/draftpaper_agile2006.txt (original) +++ pypy/extradoc/talk/agile2006/draftpaper_agile2006.txt Tue May 2 06:45:49 2006 @@ -8,24 +8,65 @@ Introduction: ============= -This paper will present the story and the experiences gathered so far in the +This paper presents the story and the experiences gathered so far in the PyPy project concerning how to integrate such diverse perspectives as agile practices being used in a distributed and dispersed development style in an Open Source project that is partly funded by the European Union. The PyPy project started as a grass-root effort among core developers in the Python language community, aiming at building a Python implementation purely -built in Python (todays main language implementation is based on C, called -Cpython. It was a language implementation project that was purely driven from -a non-profit perspective which increased in complexity when the Open Source -project applied for EU-funding. We believe that the practice of "sprinting", -as being used in the PyPy project, makes Agile and Distributed/dispersed -workstyles more possible to combine. We also believe it is a very useful -practice for creating value and ensuring quality in a projects with hybrid -cultures and methodologies. It is our aim to start to show-case this with -experiences from the first funded year of PyPy, combining Agile and -Distributed/dispersed Development in an Open Source Community with the -Plan-driven approaches through EU-Funding. +built in Python. It was a language implementation project that was purely driven from +a non-profit perspective which rapidly increased in complexity when the Open Source +project applied for EU-funding. + +Today the project have over 4 years of intense activity as a Open Source +community (F/OSS) effort and have completed a successful first year of the EU-funded effort. +In order to understand how the PyPy project managed and manages to strike a balance +between being an F/OSS community, while also having the core work of the project +being funded by the European Union (with all the structure and process requirements +that entails) we need to look at the influencing factors of the project process. + +The influencing factors of the PyPy project process are: + +- The F/OSS/Python community factor. Different Open Source communities have different +"flavours" regarding culture, communication climate, structure, decision-process +etc. PyPy was born out of the Python Community and share some of it?s characteristics +which have had a huge influence on the project process so far. Aspects such as +distributed/dispersed development and the supporting practices and infrastructure in place +to quality assure software development in a collaborated manner are part of this important +influencing factor. + +- The Agile factor. Almost a subset of the F/OSS/Python community factor - agile +practices that has been in use since the inception of the project, that in fact have +been the main drivers of the project are very much inspired by other projects in the +Python community. A key factor in this influencing factor is the Python version of +"sprinting". We will present this "agile" practice, explain and trace it?s origins within the +Python community and identify which of the main agile practices inspired the Python world +to go "sprinting" - a key technique today not only for the PyPy project but also for all main +Python projects. We will also touch on aspects such as Test Driven Development and +explain how these are implemented in PyPy. + +- The EU factor. PyPy is the first F/OSS community that organized themselves into an +EU-project, recieving EU-funding. It has had a huge impact on the project, and it is +important to identify how EU project and process requirements can be "weaved" into +and Agile F/OSS project - a challenge indeed. The EU-funding has been and still is an +enourmous opportunity, the project would not have had the rapid progress and impact it +is now having without the funding. It is also very important to note that without striking the +right balance between the three main influencing factors (F/OSS, agile and EU-funding) this +factor might also prove to be a "showstopper", something that might influence the PyPy +community negatively. This is a constant challenge - we explain here how we created +our process and added a "consortium-level" structure to the F/OSS community +and the steps we took in order to mitigate this risk. + +Our conclusion so far in the project is that we believe that the practice of "sprinting", +as being used in the PyPy project, makes Agile and Distributed/dispersed workstyles +more possible to combine. We also believe it is a very useful practice for creating value +and ensuring quality in a projects with hybrid cultures and methodologies. It is our aim to +start to show-case this with experiences from the first funded year of PyPy. We also feel +that our experiences as a unique hybrid project would be of interest to other communities +such as the agile community and we hope that this paper will encourage cross-community +interaction and communication. + Project context +++++++++++++++ @@ -33,23 +74,29 @@ Objectives: ~~~~~~~~~~~ -The Technical objective of the PyPy project is to build a implementation of the -Open Source Programming Language in the Python language itself. By employing -novel combinations of known techniques for building optimized compilers and -interpreters the project will build an implementation of Python that is easier -to read and understand than the existing implementations, while only paying a -small performance penalty. - -The Scientific objectives of the project are to investigate a number of novel -techniques based on Aspect Oriented Programming code generation and abstract -interpretation for the implementation of practical dynamic languages The goal -is to break the compromise between flexibility, simplicity and performance -trade-offs and to expand the range of directly supportable runtime platforms. - -The Method objective is to showcase a novel software engineering process: -Sprint Driven Development. This is an Agile methodology, providing a dynamic -and adaptive environment, suitable for co-operative and distributed -development. +Due to the dual nature of the project even such a thing as objectives can get +complicated. If you, as a potential PyPy user, would visit out main developer server +codespeak you would find the following statement: + +"The PyPy project aims at producing a flexible and fast Python implementation. +The guiding idea is to translate a Python-level description of the Python language +itself to lower level languages. Rumors have it that the secret goal is being faster-than-C +which is nonsense, isn't it? more..." + +Codespeak housed the F/OSS project since it?s inception and it has been a driving +strategy to continue a look-and-feel of a purely F/OSS project in order to not confuse +developers interested in just that - PyPy as a Python implementation. + +Digging a bit deeper you can find documentation which states the objectives of the +EU-funded part of the project. The EU project?s title is "PyPy" which is an acronym for +"Researching a Highly Flexible and Modular Language Platform and Implementing it by +Leveraging the Open Source Python Language and Community". The EU-project has +three objectives: one technical, one research-oriented and one methodology-oriented +objective. In short PyPy is about building an optimized compiler and interpreter purely +in Python, applying Aspect Oriented Programming and abstract interpretation techniques. +The methodology objective aims at showcasing the "sprint-driven development method" +being used by PyPy and you can view this paper as part of fullfilling the methodology +objective. Strategy: ~~~~~~~~~ @@ -62,16 +109,45 @@ strategy while also conforming to the actual requirements of the 6th Framework Programme. -The consortium consists of 8 partners: DFKI (Germany), Ab Strakt (Sweden), -Logilab (France), merlinux GmbH (Germany), tismerysoft GmbH (Germany), Change -Maker (Sweden) , Impara GmbH (Germany) and Heinrich Heine Universit?t -D?sseldorf (Germany) and 4 physical person partners: Laura Creighton (Sweden), -Richard Emslie (UK), Eric Van Riet Paap (Netherlands) , Niklaus Haldiman -(Switzerland). The project effort of work for the 2 years of funding consists -of 14 work-packages and in total 58 deliverables. +The F/OSS part of PyPy has no budget tied to it and no formal organizational structure. +There are no resources tied to it other than the volunteers participating in the development +process, ranging from the core developers and architects behind PyPy to people from all +over the world, driven by a combination of professional need and personal interest in +Python language implementations such as PyPy and choosing to contribute to PyPy. There +is also a large group of students on PHD level participating and contributing, using their +areas of interest in PyPy as thesis material. + +It is difficult to estimate the amount of people involved in PyPy but we estimate that +ca 300-500 people "follow actively" the progress of the project - this might mean +reading emails, IRC logs and documention in some cases, asking questions and +sending bug reports in other cases.There are ca 50 people that have commit-rights +to the source code. The core group of developers consists of ca 10 people. + +The EU part of the project is organized through a consortium which consists of 8 +partners: DFKI (Germany), Ab Strakt (Sweden), Logilab (France), merlinux GmbH +(Germany), tismerysoft GmbH (Germany), Change Maker (Sweden) , Impara GmbH +(Germany) and Heinrich Heine Universit?t D?sseldorf (Germany) and 4 physical +person partners: Laura Creighton (Sweden), Richard Emslie (UK), +Eric Van Riet Paap (Netherlands) , Niklaus Haldiman (Switzerland). + +The project effort of work for the 2 years of funding consists +of 14 work-packages and in total 58 deliverables which are high-level functional +and non-functional requirements that were formulated in a proposal and form the +"Description of Work" in the contract with the European Commission. The funding +recieved for this effort is 1.3 million euros. Of the core group of developers mentioned +above almost all of them (ca 10 people) are involved in some sense in the partner +companies and organizations of the PyPy consortium. History: ~~~~~~~~ +The ideas behind PyPy started via discussions on european mailing-lists in the Python +community late 2002 by people that had been active in the Python community for +some time, core developers interested in language implementation. They based +the discussions and ideas partly on their experiences with developing and driving +some well-known projects in the Python community. They met up in February 2003 +at a "sprint", a one week working meeting,to draft their ideas and to start PyPy as +an Open Source project. The sprint facilities as well as travel, accommodation and +time was financed by all participants privately. Mid 2003 the idea of trying to get EU-funding for the project was born. It became clear that the project had an arbitrarily large scale and that receiving @@ -82,53 +158,25 @@ in order to answer the question: "Should we go for it?" to which the answer quickly became "Let's see how far we get!". -There had been a growing interest from the European Commission, IST division to -look closer at the Open Source world and its achievements. Several funded -research projects in the 5th framework programme studied the phenomenon -(FLOSS-POLS, FLOSS) - its organization, business models and licensing. A few -other funded software projects used Open Source in their work as tools -(languages and applications). There was no previous experience of an Open -Source community based project making a bid for funding. - -The areas in the 6th Framework programme (second call) fit very well with the -objectives of PyPy. The idea of strengthening the European Software -development companies and businesses with supporting an open source language -implementation was new but appealing to the EU. However, being an Open Source -project was not enough. The challenges and the idea of a flexible, configurable -"translator" or "compiler" met the research targets of the FP6, as well as -trying out and documenting the agile methodology being used. - -In short, we argued that EU funding allowed the project to go from reaching a -critical mass and position to continue to evolve from there, and that it would -help European organizations to make some ground. - Acting on this strategy proved to be a more difficult task. The entire proposal and negotiation process took over a year (Autumn 2003 until November 2004).A proper description of planned work, necessary to satisfy formal requirements, had not previously been part of the development focus and both the EU and the -parties involved had to adapt to the situation. Yet, drafting the high-level -requirements (in total 14 work-packages and 58 deliverables) was done using the -same version-control/open-communication based work style, including evolving -the proposal at sprints. Writing the proposal and specifying according -objectives on a higher level has proved to be generally useful for clarifying -goals on a longer term. It also helps others to understand the project better. - -Unfortunately the negotiations with the EU got stuck in organizational limbo -and the project is still suffering from the effects of this even today. The -goal of funding contributors especially coming to sprints was originally based -on a non-profit association. This solution wasn't seen as realistic or -feasible by the EU although we think it remains a viable approach for the -future. During negotiations, we got to an alternative solution which had a few -drawbacks: contributors have to become Contract Partners within the EU-level -Consortium (which is by itself not difficult) and can then at least claim -travel and accommodation costs when attending sprints. - -However, this construction does not allow them to get paid for work time and -also has some formal requirements. In practice this leads to current -considerations of developers to shift private money between them in order to -circumvent the current problems withimplementing an agile model within the EU -contract framing. +parties involved had to adapt to the situation. +During this time of the non-funded project, 2003-2005, 6 sprints were held in various +locations in Europe, participation all funded privately. The locations hosting the sprints +were universties and private persons interested in the aims of the project. + +The contract with the EU was signed and the funded part of the project, with it?s +consortium structure, started 1 of December 2004. The funded part of the project +ends in November 2006. + +The first funded year of the project ended with a review in Brussels in January 2006, +hosted by the Commission, reviewing the 10 deliverables comprising the work of the +first year. All deliverables were accepted and based on recommendations by the external +reviewers the consortium and the Commission is now restructuring the volume of the +remaining the deliverables (although not changing the scope of the project). Influencing factors: the F/OSS Python community culture ======================================================== @@ -136,81 +184,365 @@ The Python community -------------------- +Python is an Open Source language, published under an OSI approved open source license. +It was created by Guido van Rossum and is now one of the five most used languages in the world. +Due to the nature of the language there is a strong focus on glue and integration with other +languages such as C and Java etc. Other typical aspects of the Python community is that it +houses four large language implementations as separate projects that communicate and discuss +their experiences and approaches with each other. This intra-extra community focus and interest +have created a collaborative atmosphere with an open and transparent communication climate. The +key to a lively and working community is the people factor, as always and of course so for the +Python community as well. The PyPy community ------------------ +The PyPy project is one of the four large language implementation projects in the Python community. +PyPy grew from the architectural experiences from previous successful Python projects and this +prior community experience was vital for the evolving of the PyPy community due to the established +trust in expert skills of the core developers starting PyPy - again the people factor.Thus making it easier +recruit people into the PyPy community. + +The PyPy project inherited the focus on collaborative approaches and open communication climate. +The nature of using sprints as a core technique as a way to kick-start the project as well as moving +the sprints to different locations as a strategy to encourage participation by meeting people locally +are clear examples of this. During the period of 2003-2004 6 sprints were arranged in various european +cities, hosted by universities and private persons, participation funded privately. The effect on the +evolving community was a stable subscriber participation on the development list of between 140-150 +people. After the EU-funding and the more systematic structure of sprinting every 6th week the +amount of subscribers went from ca 150 people to over 250 people. + Supporting infrastructure -------------------------- +The amount of collaborative focus and open and transparent communication in +an open source community will manifest itself in the supporting infrastructure. +In PyPy version control is the primary means of providing a secure platform for +incremental development. In PyPy, Subversion is being used, covering both +program files and documentation. Several automated mailing lists makes sure that every +person involved receives instant notification on changes - supporting peer review on all levels. + +PyPy is also in some sense very much test-driven. PyPy is one of the +primary users of a separate F/OSS project called the py.test, tools for +automated testing with PyPy developers contributing improvements to py.test. +py.test contains a sophisticated system for running tests against the Python +Standard Library, with automatic selection of overriding tests in case there is +internally developed code that overrides the Python Standard Library - +important compliance features when the project is about language implementation. +There are also powerful mechanisms for disabling specific tests and for producing +useful traceback output. There are also automatically generated web pages that +show the status of all tests as per the latest checked in test results. + +The main communication channels between developers involved in PyPy is +to discuss over IRC (Internet-Relay-Chat) - open for all that are interested. +Several mailinglists for discussions and information is also used. Webpages, +documentation, tutorials, talks and papers etc are all available on the central +developer server for everyone.A very useful feature that really supports information +and communication (the author can attest from her own experience) are the public +email archives covering the key mailinglists - going back to start of 2003. + +An extensive coding guide, published on codespeak.net (development website) +serves as an introduction to the set of specifications being used while coding PyPy. +The coding guide covers not only naming conventions but also +design, test and documentation guidelines. + +Now - all this infrastructure is being used in almost all larger open source projects and +quite a few of them are much more hierarchial and non-transparent in their communication. +In PyPy there is no hierarchy for recieving commit-rights. A newcomer to PyPy can instantly +recieve an account on the development server, with full commit rights to the version control +system. The reason why there are no constraints is that the process is very much +self-organized and managed by the developers from a social level +(peer review, code review, supporting communication channels, coaching, mentoring) and with +strong automated tools covering tests, versions and back ups covering the technical level. + +In a distributed and dispersed workstyle these two (social and technical) levels needs to be +consistent and support each other, discrepancies would be immediately noticed. As stated +before - the people factor is again evident and in order to encourage participation and +contribution there has to be trust as well as a supportive environment in order to manage a +virtual collaborative workspace. + Supporting practices -------------------- + +Another good example of the collaborative nature of the Python community is the way +which the various projects share best practices. Core developers in the PyPy project picked +up the practice of synchronization meetings as a powerful way of supporting distributed and +dispersed development, implemented by Canonical. + +Sync-meetings are weekly short coordination meetings between developers, open to +all developers active in the PyPy community, usually but not necessarily involving aspects +of EU-funded work on deliverables. These 30 minute IRC-meetings serve a weekly +synchronisation for regular discussions and integration of ongoing work. Meetings are +prepared with an agenda sent out to pypy-dev and minutes are distributed on pypy-dev and +archived in the repository with publicly accessible links.Preparing, managing and documenting +the meetings is rotated between active developers and is self-organized as well. + +Sync-meetings have proven to be a very good complement to a process in which the project +sprints every 6th week. Sync-meetings keep cohesion as well as a team focus-and-feel for +the dispersed workstyle between sprints. Influencing factors: agile practices in PyPy ============================================ -TDD ---- - -XP --- - Sprints ------- +PyPy first started during a one-week meeting, a "sprint", held at Trillke-Gut +in Hildesheim February 2003. The sprint was inspired by practices used by other +Python projects such as Zope3. Originally the sprint methodology used in the +Python community grew from practices applied by the Zope Corporation. Their +definition of a sprint was: "two-day or three-day focused development session, +in which developers pair off together in a room and focus on building a +particular subsystem". + +Tres Seaver from the Zope Corporation, one of the instigators of the sprint +method as it is used in the Python community says the following about how they +evolved the method during 2001 and 2002: + +"The motivation was to begin using as much of XP as would fit to accelerate Zope3 +development. Given the different development culture of the Zope community +(framework-centric, distributed, no "business user" present), some of the XP mantras /practices +couldn't be done directly. We decided to try to do "as much XP as possible" for short, +highly-focused sessions, with all active committers colocated." + +As Zope Corporation as well as other Python projects such as PyPy have seen is +that sprints have goals beyond the creation of software: + +- It helped evolving the community through participation and hands-on contact +with the core developers. + +- It is a live training session not only in producing code but also in the development +methods being used (TDD, pairprogramming etc, the sprint method in itself). + +- It supports activities such design decisions and high-level requirements discussions, +creating cohesion and understanding as well as minimizing risks with dispersed/distributed +work where these kind of activities can be really difficult to manage. + +The reason for naming the method sprinting, not at all connected to Scrum and +the usage of sprints in that context, according to Tres Seaver is: + +"... because of the fact that we weren't doing XP in its proper sense, which is +more like running a long-distance race, where pacing oneself is critical. +Instead, we were pushing as fast as possible in order to maximize the benefit of limited +face time. Of all the XP practices, the one we gave shortest shrift to +is "no overtime": as sprints often go far into the evening (or even +the wee hours of the morning." + +The sprint method, as well as key aspects of F/OSS supportive infrastructure and +practices was established within the project before PyPy recieved it?s EU-funding. +Thus, in the proposal,we put much emphasis on the methodology in itself when +designing the consortium level process. Examples of how this was done was that +we created a methodology objective, specific deliverables regarding documentation +of the sprint-driven methodology as well as designing a process during the 2 years +of funding in which the project and the developers sprints every 6th week. This was +taken into account when estimating the budget, adding costs for travel and +accommodation for all partner organizations - covering 14 sprints during the 2 years. +So far during the funded part of the project we have organized 10 sprints - successful +sprints from both a development, recruiting, dissemination and networking aspects. +Another important fact is that the sprints are organized by the developers and as such is +another good example of the collaborative manner of the culture of the project and the +community. + +Why did PyPy choose sprinting as a key technique? It is a method that fits +distributed teams well because it gets the team focused around visible +challenging goals while working collarobatively (pair-programming, status +meetings, discussions etc) as well as acceleratedly (short increments and +tasks, "doing" and testing instead of long startups of planning and +requirement gathering, continuous integration). This means that most of +the time a sprint is a great way of getting results and getting new +people aquainted - a good method for dissemination of knowledge and +learning within the team. + +A key insight, worthwhile for other EU-projects to ponder, is how an agile +process like sprinting is much more suited for creative work between groups of +distributed people. Traditional software development, as well as traditional +project management techniques have a tendency to hinder creativity due to the +inbuilt over-structured, segmented and control-oriented approach which in most +cases ends in less quality when results are being measured. + EU-project practices ==================== -The formal project organization required by the EU imposed more structure on -the previous more free-floating agile process. Roles and responsibilities where -staked out,conforming with the requirements of the roles but delegating as much -as possible of the responsibilities and decision-making to the core developers. -The strategy was to keep "conceptual integrity" (Brooks) of the vision and the -idea in the hands of the core developers. A somewhat negative result was the -added workload and responsibility on developers regarding EU related work. It -was also a conscious strategy to employ the same version-control/review based -scheme regarding EU documents and Consortium level issues as those being used -in the technical development. - -It remains a challenge for all partners of the consortium, universities and -companies alike, to connect an ongoing medium-scale open-source project with EU -regulations and requirements - not to speak of the fact that companies need to -fund 50% of the costs themselves. It is, in fact, too early to judge the -overall success of our approaches although we are confident that things work -out reasonably well. - Consortium structure -------------------- +Key requirements regarding organizational structures of an Framework Programme 6 +EU-project are: +- a consortium of partners performing the work described in the contract +- a project co-ordinator managing contract administration and communication +between consortium and the Commission +- a project manager, responsible for the project reaching it?s goals within the +timeframe and budget + +The challenge was to design a project process that created a minimal amount of +changes to the structure being in use in the F/OSS project. It was especially +important to maintain an open and transparent communication, even for decision on +consortium level and such. There was a fear of the EU-project adding "top-down" +structures on the F/OSS work and on the core developers instigating the project. + +We identified a minimalistic approach of management roles (project co-ordinator, project +manager, assistant project manager) and created a management team to make sure +that there was collaboration between these roles. Although the responsibility rested on +the different management roles and the management team the strategy implemented was to +delegate as much as possible of the responsibilities and decision-making to the core developers. + +The strategy was to keep "conceptual integrity" (Brooks) of the vision and the +idea in the hands of the core developers. A somewhat negative result was the +added workload and responsibility on developers regarding EU related work. +The core developers were organized into a technical board, responsible for planning +and coordinating the development work between the partners. + +This structure was the most difficult to design and implement due to the very different nature +of it?s purpose compared to the collaborative, self-organized nature of the F/OSS project - +again it succeeded the way it has because of the core developers acting as an interface between +the developer group and the consortium level work - again we see the trust aspect and the people +factor in play. + +Sprints were budgeted for and designed into the process, together with a timeplan +for all deliverables. The project was divided into three different phases, depending +on the nature of the workflow. In that sense you could describe the EU-part of the project +as a fixed-contract style of work, but with timeplan, deliverables and work package descriptions +on a high-level, not broken down into more granular tasks. + Resource tracking and reporting ------------------------------- +The nature of reporting on a consortium level is very much focused on the costs +incurred by each partner compared to budget, by the consortium on a specific +workpackage and of the consortium overall. The consortium is free to reallocate +budgeted manmonth funding between partners during the project. The project reports +costs per period - PyPy have two periods. + +Again - the need for open and transparent communication together with a collaborative +climate created the need to have what we believe a unique view on cost reporting +within the project. In PyPy all timesheets are gathered on a monthly basis and stored in +central repository, accessible for all consortium partners (managers and developers alike). +Cost claims from all partners are gathered on a six month basis. This data helps the +management board and technical board to assess the status of work. + +Templates for timesheets, costs claims, resource tracking tools etc are created in open +formats and all data is stored under the same version control that we use for the source +code. All reports are produced with docutils/ReST format which together with automated +mailinglists for covering updates in the version control repositories allows for collaborate +peer-reviewing regarding the EU-level of reports. Again the strategy was to use the same +tools and practises on consortium level work as is used in the development process. +Interesting to note is that the technical reports written for the Commission regarding certain +deliverables and progress have also been a great help towards the community who also have +free access to these reports and view them as extra, although peculiar formated, documentation. + + Communication and documentation ------------------------------- +All documentation and supporting communication infrastructure is hosted on the same developer +server as the source code, covered by the same version control system. Only a few repositories +are not public available (such as the resource tracking repositories) - but they are fully accessible +for everyone employed by a partner organization. + +The communication infrastructure being used on the consortium level of work mirrors that of the +development work - having years of experience on the distributed workstyle. In the case of PyPY +there are mailinglists as well as IRC channels for consortium level work. We even implemented a +procedure in our internal consortium agreement to allow for virtual meetings for decisions in +the consortium. So far this have been the primary meeting form and it has worked well as a channel +for making decisions. IRC-logs and minutes support the procedure. In some cases decisions have also +been made via email on the consortium mailinglist. + +Although not the primary focus it is also useful to have the regular sprints to coordinate specific issues +between some partners or between all partners, have physical meetings and discussions between +the management team and the technical board etc. + +Our funding have also resulted in the possibility to have a more unorthodox documention - the project +have experimented in filming sprints to show the development method as well as filming talks and +discussion. Our film material is planned to be released before summer 2006. + Troubles in Paradise:striking a balance ======================================= Developer driven versus formal project structure ------------------------------------------------ +The fear of a top-down, hierarchial decision process of the consortium was a justified one. +It is interesting for us to note that now, having the experience and more contractual +overview to note that there is nothing in the requirements from the Commission that forces +a project to a more traditional and strict project process. It is mostly a question of the +experience and customs of the partner companies. In that sense there was much flexibility +in designing a process that allowed for a developer driven process regarding not only software +development but also sprint administration and planning as well as consortium work. + +The majority of the partners on key roles in the consortium organization had been working +together since before the funding, procedures and best practises had been tried out. The +results from the first year showed that a minimalistic path could be identified and that the +important work would be to review and adjust the process when it did not support the work +any more, or new situations arose that we had not planned for (and that did happen!). + +Already year two has another look-and-feel to it on a consortium level when it comes to +how the management team and the technical board works, because of the different +nature of work in year two. + Agile strategies versus formal EU-contractual requirements ---------------------------------------------------------- +Our main agile practise, sprint-driven development, was successfully integrated into +the formal contractual requirements, allowing for the same free-floating agile process +of self organizing and decision making as existed before the funding, but with a more +systematic and documented style. + +But here is also our biggest failure, the main "un-agile" aspect of the entire project having +a large negative effect not only on the EU-part of the project but also on the community. +We had planned for a process that kept an "open-door" policy that allowed us to fund +non-consortium persons from the community to attend sprints. The budget was allocated, +the procedure within the sprint context of handling more newcomers were known to us - the +main showstopper was that PyPy sprint funding did not fit within the customs and practices +of contracts for cost claims in the Commission. + +Every time we want to encourage participation and fund people to participate in sprints +and contribute the procedure now is that they have to join the consortium as a full +partner - but as a "physical person".This creates the need for a contractual amendment which +adds administrative work to the project as well as for the persons in question. A too blunt +instrument and today we still do not have a working solution to this problem. It is an +unfortunate example on how the influencing factor of F/OSS, agile practices and +EU-funding collides and creates negative impact on the project. + + F/OSS community versus hierarchies for "conceptual integrity" ------------------------------------------------------------- +There are many examples of F/OSS projects and communities that have dried out +because of the fear of the architects to allow the contributors to fully participate +and also influence features and vision of the software. In PyPy this challenge comes +twofold. Not only is there a the challenge to let the core developers keep "conceptual +integrity" while also allowing the community to influence the direction and features of +the software. There is also the consortium level of work in which the core developers +could fear to "loose" the mandate of driving the architectural and design work. And +yet another layer of risk and complexity would be if the consortium level would +"shut the door" on the community, enforcing a more closed development process. + +As in many cases - being risk aware is the first step to mitigate. Because the +project is so deeply rooted in the F/OSS Python community, with it?s specific +culture and climate, and because so many people involved in the core work +on both the development and consortium level also shared this background they +took great pains to avoid situations like this to happen. In fact, what we have realized +only some months ago is that there is another risk, already partly having effect on +the community. Because of the funding the development process is progressing much +more rapidly in PyPy than more normal F/OSS projects. The speed and the dramatically +increasing learning curve could make members more passive because they do not +have the time to follow full-time IRC discussions, postings on mailinglists and the actual +source code and increasing test suites. + +This is a challenge and it is the focus of the developer group to try to distill and package +information in order to help people to better navigate the progress. + Conclusion ========== The important question is the following (and is also part of the methodological -objective of the project): is there enough room to manage a project and Ope +objective of the project): is there enough room to manage a project and Open Source community within the plan-driven inspired methods that are required in EU-funded projects, while still working agile and distributed? We believe so. The one clear dominating factor to make all this succeed is, as always, the people factor, the CRACK performers as Boehm and Turner calls them -("Collaborative, Representative, Authorized, Committed, Knowledgeable") (4). +("Collaborative, Representative, Authorized, Committed, Knowledgeable"). . The core developers of the PyPy project had the right mix of various skills in order to succeed in setting up a hybrid environment - enabling them to work @@ -237,7 +569,7 @@ communication through sprints, documentation, tutorials, mentoring, sync-meetings, thus also increasing the group of the core developers during the project - + Drawing from these different skills within the community of developers in the PyPy project one possible conclusion would be that a truly agile approach dominating the workstyle of an Open Source project will increase the ability of @@ -246,14 +578,3 @@ individuals, subgroups or the whole group). By doing this hybrid projects such as PyPy and others (Zope Europe among others) are made possible. -The vision factor ------------------ - -Managing diversities --------------------- - -Process design --------------- - -Group learning --------------- From sanxiyn at codespeak.net Tue May 2 07:32:32 2006 From: sanxiyn at codespeak.net (sanxiyn at codespeak.net) Date: Tue, 2 May 2006 07:32:32 +0200 (CEST) Subject: [pypy-svn] r26643 - in pypy/dist/pypy/translator/cl: . test Message-ID: <20060502053232.6B04110088@code0.codespeak.net> Author: sanxiyn Date: Tue May 2 07:32:19 2006 New Revision: 26643 Modified: pypy/dist/pypy/translator/cl/clrepr.py pypy/dist/pypy/translator/cl/gencl.py pypy/dist/pypy/translator/cl/opformatter.py pypy/dist/pypy/translator/cl/test/test_call.py Log: Implement op_indirect_call Modified: pypy/dist/pypy/translator/cl/clrepr.py ============================================================================== --- pypy/dist/pypy/translator/cl/clrepr.py (original) +++ pypy/dist/pypy/translator/cl/clrepr.py Tue May 2 07:32:19 2006 @@ -107,7 +107,7 @@ return "'" + repr_class(item) def repr_static_method(item): - return clrepr(item.value._name, symbol=True) + return "'" + clrepr(item.value._name, symbol=True) dispatch = { Class: repr_class, Modified: pypy/dist/pypy/translator/cl/gencl.py ============================================================================== --- pypy/dist/pypy/translator/cl/gencl.py (original) +++ pypy/dist/pypy/translator/cl/gencl.py Tue May 2 07:32:19 2006 @@ -1,7 +1,7 @@ import types from pypy.tool.udir import udir -from pypy.objspace.flow.model import Constant, c_last_exception +from pypy.objspace.flow.model import Constant, c_last_exception, FunctionGraph from pypy.translator.translator import graphof from pypy.rpython.ootypesystem.ootype import dynamicType, oodowncast, Record, Instance, _class, _static_meth, _meth, ROOT from pypy.rpython.ootypesystem.rclass import OBJECT @@ -163,6 +163,10 @@ name = obj._method_name # XXX for line in self.emit_defmethod(graph, name): yield line + elif isinstance(obj, FunctionGraph): + graph = obj + for line in self.emit_defun(graph): + yield line def emit_defun(self, fun): yield "(defun " + clrepr(fun.name, symbol=True) Modified: pypy/dist/pypy/translator/cl/opformatter.py ============================================================================== --- pypy/dist/pypy/translator/cl/opformatter.py (original) +++ pypy/dist/pypy/translator/cl/opformatter.py Tue May 2 07:32:19 2006 @@ -61,12 +61,20 @@ yield "(setf %s (not (zerop %s)))" % (clrepr(result, True), clrepr(arg, True)) - def op_direct_call(self, result, fun, *args): + def op_direct_call(self, result, _, *args): funobj = self.args[0].value self.gen.pendinggraphs.append(funobj) + fun = clrepr(funobj._name, symbol=True) funcall = " ".join((fun,) + args) yield "(setf %s (%s))" % (result, funcall) + def op_indirect_call(self, result, fun, *args): + graphs = self.args[-1].value + self.gen.pendinggraphs.extend(graphs) + args = args[:-1] + funcall = " ".join((fun,) + args) + yield "(setf %s (funcall %s))" % (result, funcall) + def op_new(self, result, _): cls = self.args[0].value if isinstance(cls, List): Modified: pypy/dist/pypy/translator/cl/test/test_call.py ============================================================================== --- pypy/dist/pypy/translator/cl/test/test_call.py (original) +++ pypy/dist/pypy/translator/cl/test/test_call.py Tue May 2 07:32:19 2006 @@ -9,3 +9,20 @@ return n + 1 cl_add_one = make_cl_func(add_one, [int]) assert cl_add_one(1) == 2 + +def test_indirect_call(): + def add_one(n): + return n + 1 + def add_two(n): + return n + 2 + def pick_function(flag): + if flag: + return add_one + else: + return add_two + def add_one_or_two(n, flag): + function = pick_function(flag) + return function(n) + cl_add_one_or_two = make_cl_func(add_one_or_two, [int, bool]) + assert cl_add_one_or_two(8, True) == 9 + assert cl_add_one_or_two(7, False) == 9 From sanxiyn at codespeak.net Tue May 2 07:37:50 2006 From: sanxiyn at codespeak.net (sanxiyn at codespeak.net) Date: Tue, 2 May 2006 07:37:50 +0200 (CEST) Subject: [pypy-svn] r26644 - pypy/dist/pypy/translator/cl/test Message-ID: <20060502053750.F078B10088@code0.codespeak.net> Author: sanxiyn Date: Tue May 2 07:37:47 2006 New Revision: 26644 Modified: pypy/dist/pypy/translator/cl/test/test_call.py Log: Rename a test Modified: pypy/dist/pypy/translator/cl/test/test_call.py ============================================================================== --- pypy/dist/pypy/translator/cl/test/test_call.py (original) +++ pypy/dist/pypy/translator/cl/test/test_call.py Tue May 2 07:37:47 2006 @@ -3,11 +3,11 @@ def test_call(): def add_one(n): - n = add_one_really(n) - return n - def add_one_really(n): return n + 1 - cl_add_one = make_cl_func(add_one, [int]) + def call_add_one(n): + n = add_one(n) + return n + cl_add_one = make_cl_func(call_add_one, [int]) assert cl_add_one(1) == 2 def test_indirect_call(): From sanxiyn at codespeak.net Tue May 2 08:29:14 2006 From: sanxiyn at codespeak.net (sanxiyn at codespeak.net) Date: Tue, 2 May 2006 08:29:14 +0200 (CEST) Subject: [pypy-svn] r26650 - pypy/dist/pypy/translator/cl Message-ID: <20060502062914.D57D510088@code0.codespeak.net> Author: sanxiyn Date: Tue May 2 08:29:11 2006 New Revision: 26650 Modified: pypy/dist/pypy/translator/cl/gencl.py Log: Move null instance check one level up Modified: pypy/dist/pypy/translator/cl/gencl.py ============================================================================== --- pypy/dist/pypy/translator/cl/gencl.py (original) +++ pypy/dist/pypy/translator/cl/gencl.py Tue May 2 08:29:11 2006 @@ -3,7 +3,7 @@ from pypy.tool.udir import udir from pypy.objspace.flow.model import Constant, c_last_exception, FunctionGraph from pypy.translator.translator import graphof -from pypy.rpython.ootypesystem.ootype import dynamicType, oodowncast, Record, Instance, _class, _static_meth, _meth, ROOT +from pypy.rpython.ootypesystem.ootype import dynamicType, oodowncast, null, Record, Instance, _class, _static_meth, _meth, ROOT from pypy.rpython.ootypesystem.rclass import OBJECT from pypy.translator.cl.clrepr import clrepr from pypy.translator.cl.opformatter import OpFormatter @@ -38,6 +38,9 @@ def check_declaration(self, arg): if isinstance(arg, Constant): + if isinstance(arg.concretetype, (Record, Instance)): + if arg.value is null(arg.concretetype): + return "nil" if isinstance(arg.concretetype, Instance): return self.declare_constant_instance(arg) return clrepr(arg) @@ -106,8 +109,6 @@ # const.concretetype is Instance if const in self.declarations: return self.declarations[const][0] - if const.value is const.concretetype._null: - return "nil" name = "const" + str(self.constcount) INST = dynamicType(const.value) self.declare_class(INST) From sanxiyn at codespeak.net Tue May 2 08:30:48 2006 From: sanxiyn at codespeak.net (sanxiyn at codespeak.net) Date: Tue, 2 May 2006 08:30:48 +0200 (CEST) Subject: [pypy-svn] r26651 - pypy/dist/pypy/translator/cl/test Message-ID: <20060502063048.8A46210091@code0.codespeak.net> Author: sanxiyn Date: Tue May 2 08:30:45 2006 New Revision: 26651 Added: pypy/dist/pypy/translator/cl/test/test_tuple.py Log: Tuple tests. Passed without any additional work. Added: pypy/dist/pypy/translator/cl/test/test_tuple.py ============================================================================== --- (empty file) +++ pypy/dist/pypy/translator/cl/test/test_tuple.py Tue May 2 08:30:45 2006 @@ -0,0 +1,17 @@ +from pypy.translator.cl.buildcl import make_cl_func + +def test_tuple_get(): + def tuple_get(number): + tuple = (number,) + return tuple[0] + cl_tuple_get = make_cl_func(tuple_get, [int]) + assert cl_tuple_get(1) == 1 + +def test_tuple_iter(): + def tuple_double(number): + tuple = (number,) + for item in tuple: + number += item + return number + cl_double = make_cl_func(tuple_double, [int]) + assert cl_double(1) == 2 From antocuni at codespeak.net Tue May 2 11:43:15 2006 From: antocuni at codespeak.net (antocuni at codespeak.net) Date: Tue, 2 May 2006 11:43:15 +0200 (CEST) Subject: [pypy-svn] r26655 - in pypy/dist/pypy/translator/cli: . src test Message-ID: <20060502094315.ABAC1100B5@code0.codespeak.net> Author: antocuni Date: Tue May 2 11:43:09 2006 New Revision: 26655 Modified: pypy/dist/pypy/translator/cli/oopspec.py pypy/dist/pypy/translator/cli/src/pypylib.cs pypy/dist/pypy/translator/cli/test/compile.py Log: Forwarding 'list.append' oopspec to the builtin 'Add' instead of the manual written 'append'. Modified: pypy/dist/pypy/translator/cli/oopspec.py ============================================================================== --- pypy/dist/pypy/translator/cli/oopspec.py (original) +++ pypy/dist/pypy/translator/cli/oopspec.py Tue May 2 11:43:09 2006 @@ -36,6 +36,6 @@ BUILTIN_METHODS = { List : { - 'append': Meth([List.ITEMTYPE_T], Void) + 'Add': Meth([List.ITEMTYPE_T], Void) } } Modified: pypy/dist/pypy/translator/cli/src/pypylib.cs ============================================================================== --- pypy/dist/pypy/translator/cli/src/pypylib.cs (original) +++ pypy/dist/pypy/translator/cli/src/pypylib.cs Tue May 2 11:43:09 2006 @@ -59,12 +59,12 @@ } } + /* public void append(T item) { this.Add(item); } - /* public void extend(List other) { this.AddRange(other); Modified: pypy/dist/pypy/translator/cli/test/compile.py ============================================================================== --- pypy/dist/pypy/translator/cli/test/compile.py (original) +++ pypy/dist/pypy/translator/cli/test/compile.py Tue May 2 11:43:09 2006 @@ -28,11 +28,17 @@ def __init__(self, x): self.x = x +def foo(a, b): + pass + +from pypy.rpython.rarithmetic import ovfcheck + def bar(x, y): - t = (x,y) - return t[0] -# f = Foo(3) -# return f.x + try: + l = [x, y] + return l[0] + except IndexError: + return 0 f = compile_function(bar, [int, int]) From pedronis at codespeak.net Tue May 2 13:56:11 2006 From: pedronis at codespeak.net (pedronis at codespeak.net) Date: Tue, 2 May 2006 13:56:11 +0200 (CEST) Subject: [pypy-svn] r26659 - in pypy/dist/pypy: interpreter module/__builtin__ objspace objspace/std objspace/test Message-ID: <20060502115611.0026B100A7@code0.codespeak.net> Author: pedronis Date: Tue May 2 13:56:09 2006 New Revision: 26659 Modified: pypy/dist/pypy/interpreter/baseobjspace.py pypy/dist/pypy/interpreter/mixedmodule.py pypy/dist/pypy/module/__builtin__/operation.py pypy/dist/pypy/objspace/descroperation.py pypy/dist/pypy/objspace/std/objspace.py pypy/dist/pypy/objspace/test/test_descroperation.py Log: make test_builtin pass again. Make intern behavior more similar to CPython, also discovered that setattr doesn't anymore force attribute names to be string in 2.4 . Modified: pypy/dist/pypy/interpreter/baseobjspace.py ============================================================================== --- pypy/dist/pypy/interpreter/baseobjspace.py (original) +++ pypy/dist/pypy/interpreter/baseobjspace.py Tue May 2 13:56:09 2006 @@ -385,6 +385,15 @@ else: return self.w_False + def new_interned_w_str(self, w_s): + s = self.str_w(w_s) + try: + return self.interned_strings[s] + except KeyError: + pass + self.interned_strings[s] = w_s + return w_s + def new_interned_str(self, s): try: return self.interned_strings[s] Modified: pypy/dist/pypy/interpreter/mixedmodule.py ============================================================================== --- pypy/dist/pypy/interpreter/mixedmodule.py (original) +++ pypy/dist/pypy/interpreter/mixedmodule.py Tue May 2 13:56:09 2006 @@ -34,7 +34,7 @@ w_value = space.finditem(self.w_dict, w_name) if self.lazy and w_value is None: name = space.str_w(w_name) - w_name = space.new_interned_str(name) + w_name = space.new_interned_w_str(w_name) try: loader = self.loaders[name] except KeyError: Modified: pypy/dist/pypy/module/__builtin__/operation.py ============================================================================== --- pypy/dist/pypy/module/__builtin__/operation.py (original) +++ pypy/dist/pypy/module/__builtin__/operation.py Tue May 2 13:56:09 2006 @@ -162,7 +162,7 @@ def intern(space, w_str): if space.is_w(space.type(w_str), space.w_str): - return space.new_interned_str(space.str_w(w_str)) + return space.new_interned_w_str(w_str) raise OperationError(space.w_TypeError, space.wrap("intern() argument 1 must be string.")) def callable(space, w_object): Modified: pypy/dist/pypy/objspace/descroperation.py ============================================================================== --- pypy/dist/pypy/objspace/descroperation.py (original) +++ pypy/dist/pypy/objspace/descroperation.py Tue May 2 13:56:09 2006 @@ -36,9 +36,6 @@ return w_dict = w_obj.getdict() if w_dict is not None: - # note: don't use w_name as a key in w_dict directly -- the expected - # result of setattr() is that it never stores subclasses of 'str' - # in the __dict__ space.set_str_keyed_item(w_dict, w_name, w_value) return raiseattrerror(space, w_obj, name, w_descr) Modified: pypy/dist/pypy/objspace/std/objspace.py ============================================================================== --- pypy/dist/pypy/objspace/std/objspace.py (original) +++ pypy/dist/pypy/objspace/std/objspace.py Tue May 2 13:56:09 2006 @@ -453,8 +453,6 @@ def set_str_keyed_item(self, w_obj, w_key, w_value): # performance shortcut to avoid creating the OperationError(KeyError) - if type(w_key) is not W_StringObject: - w_key = self.new_interned_str(self.str_w(w_key)) if type(w_obj) is W_DictObject: w_obj.content[w_key] = w_value else: Modified: pypy/dist/pypy/objspace/test/test_descroperation.py ============================================================================== --- pypy/dist/pypy/objspace/test/test_descroperation.py (original) +++ pypy/dist/pypy/objspace/test/test_descroperation.py Tue May 2 13:56:09 2006 @@ -189,8 +189,10 @@ s = S("abc") setattr(s, s, s) assert len(s.__dict__) == 1 - assert type(s.__dict__.keys()[0]) is str # don't store S keys - assert s.abc is s + # this behavior changed in 2.4 + #assert type(s.__dict__.keys()[0]) is str # don't store S keys + #assert s.abc is s + getattr(s,s) is s def test_notimplemented(self): #import types From pedronis at codespeak.net Tue May 2 14:08:47 2006 From: pedronis at codespeak.net (pedronis at codespeak.net) Date: Tue, 2 May 2006 14:08:47 +0200 (CEST) Subject: [pypy-svn] r26662 - pypy/dist/pypy/rpython Message-ID: <20060502120847.0FAA1100B7@code0.codespeak.net> Author: pedronis Date: Tue May 2 14:08:45 2006 New Revision: 26662 Modified: pypy/dist/pypy/rpython/llinterp.py Log: make test_gc pass again. Modified: pypy/dist/pypy/rpython/llinterp.py ============================================================================== --- pypy/dist/pypy/rpython/llinterp.py (original) +++ pypy/dist/pypy/rpython/llinterp.py Tue May 2 14:08:45 2006 @@ -46,13 +46,12 @@ # XXX hack: set gc to None because # prepare_graphs_and_create_gc might already use the llinterpreter! self.gc = None + self.tracer = None if hasattr(heap, "prepare_graphs_and_create_gc"): flowgraphs = typer.annotator.translator.graphs self.gc = heap.prepare_graphs_and_create_gc(self, flowgraphs) if self.TRACING: self.tracer = Tracer() - else: - self.tracer = None def eval_graph(self, graph, args=()): llframe = LLFrame(graph, args, self) From pedronis at codespeak.net Tue May 2 14:46:55 2006 From: pedronis at codespeak.net (pedronis at codespeak.net) Date: Tue, 2 May 2006 14:46:55 +0200 (CEST) Subject: [pypy-svn] r26665 - in pypy/dist/pypy: annotation jit/hintannotator rpython translator/goal translator/stackless Message-ID: <20060502124655.6B5881008A@code0.codespeak.net> Author: pedronis Date: Tue May 2 14:46:51 2006 New Revision: 26665 Modified: pypy/dist/pypy/annotation/annrpython.py pypy/dist/pypy/annotation/bookkeeper.py pypy/dist/pypy/jit/hintannotator/bookkeeper.py pypy/dist/pypy/rpython/rtyper.py pypy/dist/pypy/translator/goal/query.py pypy/dist/pypy/translator/stackless/transform.py Log: issue166: testing converted RPythonAnnotator.binding interface to be like dict.get taking an optional default or raising KeyError if the default is not specified. Modified: pypy/dist/pypy/annotation/annrpython.py ============================================================================== --- pypy/dist/pypy/annotation/annrpython.py (original) +++ pypy/dist/pypy/annotation/annrpython.py Tue May 2 14:46:51 2006 @@ -15,6 +15,7 @@ class AnnotatorError(Exception): pass +FAIL = object() class RPythonAnnotator: """Block annotator for RPython. @@ -136,7 +137,7 @@ # recursively proceed until no more pending block is left if complete_now: self.complete() - return self.binding(flowgraph.getreturnvar(), extquery=True) + return self.binding(flowgraph.getreturnvar(), None) def gettype(self, variable): """Return the known type of a control flow graph variable, @@ -217,14 +218,14 @@ # policy-dependent computation self.bookkeeper.compute_at_fixpoint() - def binding(self, arg, extquery=False): + def binding(self, arg, default=FAIL): "Gives the SomeValue corresponding to the given Variable or Constant." if isinstance(arg, Variable): try: return self.bindings[arg] except KeyError: - if extquery: - return None + if default is not FAIL: + return default else: raise elif isinstance(arg, Constant): Modified: pypy/dist/pypy/annotation/bookkeeper.py ============================================================================== --- pypy/dist/pypy/annotation/bookkeeper.py (original) +++ pypy/dist/pypy/annotation/bookkeeper.py Tue May 2 14:46:51 2006 @@ -207,7 +207,7 @@ if op.opname in ('simple_call', 'call_args'): yield op # some blocks are partially annotated - if binding(op.result, extquery=True) is None: + if binding(op.result, None) is None: break # ignore the unannotated part for call_op in call_sites(): @@ -235,9 +235,7 @@ s_callable = self.immutablevalue(adtmeth.func) args_s = [SomePtr(adtmeth.ll_ptrtype)] + args_s if isinstance(s_callable, SomePBC): - s_result = binding(call_op.result, extquery=True) - if s_result is None: - s_result = s_ImpossibleValue + s_result = binding(call_op.result, s_ImpossibleValue) self.consider_call_site_for_pbc(s_callable, call_op.opname, args_s, s_result) @@ -577,9 +575,7 @@ fn, block, i = self.position_key op = block.operations[i] s_previous_result = self.annotator.binding(op.result, - extquery=True) - if s_previous_result is None: - s_previous_result = s_ImpossibleValue + s_ImpossibleValue) else: if emulated is True: whence = None Modified: pypy/dist/pypy/jit/hintannotator/bookkeeper.py ============================================================================== --- pypy/dist/pypy/jit/hintannotator/bookkeeper.py (original) +++ pypy/dist/pypy/jit/hintannotator/bookkeeper.py Tue May 2 14:46:51 2006 @@ -97,9 +97,7 @@ def current_op_binding(self): _, block, i = self.position_key op = block.operations[i] - hs_res = self.annotator.binding(op.result, extquery=True) - if hs_res is None: - hs_res = annmodel.s_ImpossibleValue + hs_res = self.annotator.binding(op.result, annmodel.s_ImpossibleValue) return hs_res def getvirtualcontainerdef(self, TYPE, constructor=None): Modified: pypy/dist/pypy/rpython/rtyper.py ============================================================================== --- pypy/dist/pypy/rpython/rtyper.py (original) +++ pypy/dist/pypy/rpython/rtyper.py Tue May 2 14:46:51 2006 @@ -137,9 +137,7 @@ return result def binding(self, var): - s_obj = self.annotator.binding(var, True) - if s_obj is None: - s_obj = annmodel.SomeObject() + s_obj = self.annotator.binding(var, annmodel.SomeObject()) return s_obj def bindingrepr(self, var): Modified: pypy/dist/pypy/translator/goal/query.py ============================================================================== --- pypy/dist/pypy/translator/goal/query.py (original) +++ pypy/dist/pypy/translator/goal/query.py Tue May 2 14:46:51 2006 @@ -33,7 +33,7 @@ def visit(block): if isinstance(block, flowmodel.Block): for v in block.getvariables(): - s = annotator.binding(v, extquery=True) + s = annotator.binding(v, None) if s and s.__class__ == annmodel.SomeObject and s.knowntype != type: raise Found for g in translator.graphs: @@ -47,8 +47,8 @@ annotator = translator.annotator for graph in translator.graphs: et, ev = graph.exceptblock.inputargs - s_et = annotator.binding(et, extquery=True) - s_ev = annotator.binding(ev, extquery=True) + s_et = annotator.binding(et, None) + s_ev = annotator.binding(ev, None) if s_et: if s_et.knowntype == type: if s_et.__class__ == annmodel.SomeObject: Modified: pypy/dist/pypy/translator/stackless/transform.py ============================================================================== --- pypy/dist/pypy/translator/stackless/transform.py (original) +++ pypy/dist/pypy/translator/stackless/transform.py Tue May 2 14:46:51 2006 @@ -349,7 +349,7 @@ # about annotations :( ann = self.translator.annotator for f, t in zip(link.args, link.target.inputargs): - nb = ann.binding(f, True) + nb = ann.binding(f, None) if nb is not None: ann.setbinding(t, nb) block.exitswitch = model.c_last_exception From bea at codespeak.net Tue May 2 14:54:26 2006 From: bea at codespeak.net (bea at codespeak.net) Date: Tue, 2 May 2006 14:54:26 +0200 (CEST) Subject: [pypy-svn] r26666 - pypy/extradoc/talk/agile2006 Message-ID: <20060502125426.68F561008A@code0.codespeak.net> Author: bea Date: Tue May 2 14:54:25 2006 New Revision: 26666 Modified: pypy/extradoc/talk/agile2006/draftpaper_agile2006.txt Log: added abstract and made minor corrections - please help and review... Modified: pypy/extradoc/talk/agile2006/draftpaper_agile2006.txt ============================================================================== --- pypy/extradoc/talk/agile2006/draftpaper_agile2006.txt (original) +++ pypy/extradoc/talk/agile2006/draftpaper_agile2006.txt Tue May 2 14:54:25 2006 @@ -3,7 +3,22 @@ =================================================================================== Abstract: -(200 words - write last) + +PyPy is an Open Source project, partly funded by the European Union, employing +agile techniques evolved within the Python Community such as "sprint-driven +development".The project started as a grass-root F/OSS effort in late 2002 +and recieved EU-funding from December 2004 until November 2006. +In this paper we will present the various influencing factors that creates +the hybrid project process that is PyPy. These influencing factors are the F/OSS +Python Community (climate of the community from which PyPy grew from), agile +practices (such as the Python community evolved technique of "sprinting") and the +EU funding practices (resource tracking and reporting) impacting the project. These +influencing factors laid the foundation for the custom-made project process that +makes this unique hybrid project work and the main factor for driving this process +is the skills of the team of core developers instigating the project. PyPy, with it?s +open and transparent communication and collaborative workstyle, is again a proof +that the best agile practice is the people factor. + Introduction: ============= @@ -49,7 +64,7 @@ - The EU factor. PyPy is the first F/OSS community that organized themselves into an EU-project, recieving EU-funding. It has had a huge impact on the project, and it is important to identify how EU project and process requirements can be "weaved" into -and Agile F/OSS project - a challenge indeed. The EU-funding has been and still is an +an Agile F/OSS project - a challenge indeed. The EU-funding has been and still is an enourmous opportunity, the project would not have had the rapid progress and impact it is now having without the funding. It is also very important to note that without striking the right balance between the three main influencing factors (F/OSS, agile and EU-funding) this @@ -164,10 +179,6 @@ had not previously been part of the development focus and both the EU and the parties involved had to adapt to the situation. -During this time of the non-funded project, 2003-2005, 6 sprints were held in various -locations in Europe, participation all funded privately. The locations hosting the sprints -were universties and private persons interested in the aims of the project. - The contract with the EU was signed and the funded part of the project, with it?s consortium structure, started 1 of December 2004. The funded part of the project ends in November 2006. @@ -238,8 +249,8 @@ Several mailinglists for discussions and information is also used. Webpages, documentation, tutorials, talks and papers etc are all available on the central developer server for everyone.A very useful feature that really supports information -and communication (the author can attest from her own experience) are the public -email archives covering the key mailinglists - going back to start of 2003. +and communication (the author can attest to this from her own experience) are the public +email archives covering the key mailinglists - going back to the start of 2003. An extensive coding guide, published on codespeak.net (development website) serves as an introduction to the set of specifications being used while coding PyPy. @@ -305,16 +316,16 @@ couldn't be done directly. We decided to try to do "as much XP as possible" for short, highly-focused sessions, with all active committers colocated." -As Zope Corporation as well as other Python projects such as PyPy have seen is +Zope Corporation as well as other Python projects such as PyPy have seen that sprints have goals beyond the creation of software: -- It helped evolving the community through participation and hands-on contact +- It helped to evolve the community through participation and hands-on contact with the core developers. - It is a live training session not only in producing code but also in the development methods being used (TDD, pairprogramming etc, the sprint method in itself). -- It supports activities such design decisions and high-level requirements discussions, +- It supports activities such as design decisions and high-level requirements discussions, creating cohesion and understanding as well as minimizing risks with dispersed/distributed work where these kind of activities can be really difficult to manage. @@ -346,7 +357,7 @@ Why did PyPy choose sprinting as a key technique? It is a method that fits distributed teams well because it gets the team focused around visible challenging goals while working collarobatively (pair-programming, status -meetings, discussions etc) as well as acceleratedly (short increments and +meetings, discussions etc) as well as accelerated (short increments and tasks, "doing" and testing instead of long startups of planning and requirement gathering, continuous integration). This means that most of the time a sprint is a great way of getting results and getting new @@ -510,7 +521,7 @@ There are many examples of F/OSS projects and communities that have dried out because of the fear of the architects to allow the contributors to fully participate and also influence features and vision of the software. In PyPy this challenge comes -twofold. Not only is there a the challenge to let the core developers keep "conceptual +twofold. Not only is there a challenge to let the core developers keep "conceptual integrity" while also allowing the community to influence the direction and features of the software. There is also the consortium level of work in which the core developers could fear to "loose" the mandate of driving the architectural and design work. And From cfbolz at codespeak.net Tue May 2 15:20:52 2006 From: cfbolz at codespeak.net (cfbolz at codespeak.net) Date: Tue, 2 May 2006 15:20:52 +0200 (CEST) Subject: [pypy-svn] r26667 - pypy/extradoc/talk/agile2006 Message-ID: <20060502132052.7C90C100A0@code0.codespeak.net> Author: cfbolz Date: Tue May 2 15:20:51 2006 New Revision: 26667 Added: pypy/extradoc/talk/agile2006/draftpaper_agile2006.pdf (contents, props changed) Modified: pypy/extradoc/talk/agile2006/draftpaper_agile2006.txt Log: first version of the pdf, does not follow the conference guidelines yet Added: pypy/extradoc/talk/agile2006/draftpaper_agile2006.pdf ============================================================================== Binary file. No diff available. Modified: pypy/extradoc/talk/agile2006/draftpaper_agile2006.txt ============================================================================== --- pypy/extradoc/talk/agile2006/draftpaper_agile2006.txt (original) +++ pypy/extradoc/talk/agile2006/draftpaper_agile2006.txt Tue May 2 15:20:51 2006 @@ -1,120 +1,135 @@ =================================================================================== -Title: "Trouble in Paradise: Open Source projects, EU-funding and Agile practices" +Trouble in Paradise: Open Source projects, EU-funding and Agile practices =================================================================================== -Abstract: +.. raw:: latex + + \author{Bea Duering} + \begin{abstract} PyPy is an Open Source project, partly funded by the European Union, employing -agile techniques evolved within the Python Community such as "sprint-driven -development".The project started as a grass-root F/OSS effort in late 2002 -and recieved EU-funding from December 2004 until November 2006. -In this paper we will present the various influencing factors that creates -the hybrid project process that is PyPy. These influencing factors are the F/OSS -Python Community (climate of the community from which PyPy grew from), agile -practices (such as the Python community evolved technique of "sprinting") and the -EU funding practices (resource tracking and reporting) impacting the project. These -influencing factors laid the foundation for the custom-made project process that -makes this unique hybrid project work and the main factor for driving this process -is the skills of the team of core developers instigating the project. PyPy, with it?s -open and transparent communication and collaborative workstyle, is again a proof -that the best agile practice is the people factor. +agile techniques evolved within the Python Community such as "sprint-driven +development".The project started as a grass-root F/OSS effort in late 2002 and +recieved EU-funding from December 2004 until November 2006. In this paper we +will present the various influencing factors that creates the hybrid project +process that is PyPy. These influencing factors are the F/OSS Python Community +(climate of the community from which PyPy grew from), agile practices (such as +the Python community evolved technique of "sprinting") and the EU funding +practices (resource tracking and reporting) impacting the project. These +influencing factors laid the foundation for the custom-made project process +that makes this unique hybrid project work and the main factor for driving this +process is the skills of the team of core developers instigating the project. +PyPy, with it?s open and transparent communication and collaborative workstyle, +is again a proof that the best agile practice is the people factor. + +.. raw:: latex + + \end{abstract} + Introduction: ============= -This paper presents the story and the experiences gathered so far in the -PyPy project concerning how to integrate such diverse perspectives as agile +This paper presents the story and the experiences gathered so far in the PyPy +project concerning how to integrate such diverse perspectives as agile practices being used in a distributed and dispersed development style in an Open Source project that is partly funded by the European Union. The PyPy project started as a grass-root effort among core developers in the Python language community, aiming at building a Python implementation purely -built in Python. It was a language implementation project that was purely driven from -a non-profit perspective which rapidly increased in complexity when the Open Source -project applied for EU-funding. - -Today the project have over 4 years of intense activity as a Open Source -community (F/OSS) effort and have completed a successful first year of the EU-funded effort. -In order to understand how the PyPy project managed and manages to strike a balance -between being an F/OSS community, while also having the core work of the project -being funded by the European Union (with all the structure and process requirements -that entails) we need to look at the influencing factors of the project process. +built in Python. It was a language implementation project that was purely +driven from a non-profit perspective which rapidly increased in complexity when +the Open Source project applied for EU-funding. + +Today the project have over 4 years of intense activity as a Open Source +community (F/OSS) effort and have completed a successful first year of the +EU-funded effort. In order to understand how the PyPy project managed and +manages to strike a balance between being an F/OSS community, while also having +the core work of the project being funded by the European Union (with all the +structure and process requirements that entails) we need to look at the +influencing factors of the project process. The influencing factors of the PyPy project process are: -- The F/OSS/Python community factor. Different Open Source communities have different -"flavours" regarding culture, communication climate, structure, decision-process -etc. PyPy was born out of the Python Community and share some of it?s characteristics -which have had a huge influence on the project process so far. Aspects such as -distributed/dispersed development and the supporting practices and infrastructure in place -to quality assure software development in a collaborated manner are part of this important -influencing factor. - -- The Agile factor. Almost a subset of the F/OSS/Python community factor - agile -practices that has been in use since the inception of the project, that in fact have -been the main drivers of the project are very much inspired by other projects in the -Python community. A key factor in this influencing factor is the Python version of -"sprinting". We will present this "agile" practice, explain and trace it?s origins within the -Python community and identify which of the main agile practices inspired the Python world -to go "sprinting" - a key technique today not only for the PyPy project but also for all main -Python projects. We will also touch on aspects such as Test Driven Development and -explain how these are implemented in PyPy. - -- The EU factor. PyPy is the first F/OSS community that organized themselves into an -EU-project, recieving EU-funding. It has had a huge impact on the project, and it is -important to identify how EU project and process requirements can be "weaved" into -an Agile F/OSS project - a challenge indeed. The EU-funding has been and still is an -enourmous opportunity, the project would not have had the rapid progress and impact it -is now having without the funding. It is also very important to note that without striking the -right balance between the three main influencing factors (F/OSS, agile and EU-funding) this -factor might also prove to be a "showstopper", something that might influence the PyPy -community negatively. This is a constant challenge - we explain here how we created -our process and added a "consortium-level" structure to the F/OSS community -and the steps we took in order to mitigate this risk. - -Our conclusion so far in the project is that we believe that the practice of "sprinting", -as being used in the PyPy project, makes Agile and Distributed/dispersed workstyles -more possible to combine. We also believe it is a very useful practice for creating value -and ensuring quality in a projects with hybrid cultures and methodologies. It is our aim to -start to show-case this with experiences from the first funded year of PyPy. We also feel -that our experiences as a unique hybrid project would be of interest to other communities -such as the agile community and we hope that this paper will encourage cross-community -interaction and communication. +- The F/OSS/Python community factor. Different Open Source communities have + different "flavours" regarding culture, communication climate, structure, + decision-process etc. PyPy was born out of the Python Community and share + some of it?s characteristics which have had a huge influence on the project + process so far. Aspects such as distributed/dispersed development and the + supporting practices and infrastructure in place to quality assure software + development in a collaborated manner are part of this important influencing + factor. + +- The Agile factor. Almost a subset of the F/OSS/Python community factor - + agile practices that has been in use since the inception of the project, that + in fact have been the main drivers of the project are very much inspired by + other projects in the Python community. A key factor in this influencing + factor is the Python version of "sprinting". We will present this "agile" + practice, explain and trace it?s origins within the Python community and + identify which of the main agile practices inspired the Python world to go + "sprinting" - a key technique today not only for the PyPy project but also + for all main Python projects. We will also touch on aspects such as Test + Driven Development and explain how these are implemented in PyPy. + +- The EU factor. PyPy is the first F/OSS community that organized themselves + into an EU-project, recieving EU-funding. It has had a huge impact on the + project, and it is important to identify how EU project and process + requirements can be "weaved" into an Agile F/OSS project - a challenge + indeed. The EU-funding has been and still is an enourmous opportunity, the + project would not have had the rapid progress and impact it is now having + without the funding. It is also very important to note that without striking + the right balance between the three main influencing factors (F/OSS, agile + and EU-funding) this factor might also prove to be a "showstopper", something + that might influence the PyPy community negatively. This is a constant + challenge - we explain here how we created our process and added a + "consortium-level" structure to the F/OSS community and the steps we took in + order to mitigate this risk. + +Our conclusion so far in the project is that we believe that the practice of +"sprinting", as being used in the PyPy project, makes Agile and +Distributed/dispersed workstyles more possible to combine. We also believe it +is a very useful practice for creating value and ensuring quality in a projects +with hybrid cultures and methodologies. It is our aim to start to show-case +this with experiences from the first funded year of PyPy. We also feel that our +experiences as a unique hybrid project would be of interest to other +communities such as the agile community and we hope that this paper will +encourage cross-community interaction and communication. Project context -+++++++++++++++ +--------------- Objectives: -~~~~~~~~~~~ ++++++++++++ -Due to the dual nature of the project even such a thing as objectives can get -complicated. If you, as a potential PyPy user, would visit out main developer server -codespeak you would find the following statement: - -"The PyPy project aims at producing a flexible and fast Python implementation. -The guiding idea is to translate a Python-level description of the Python language -itself to lower level languages. Rumors have it that the secret goal is being faster-than-C -which is nonsense, isn't it? more..." - -Codespeak housed the F/OSS project since it?s inception and it has been a driving -strategy to continue a look-and-feel of a purely F/OSS project in order to not confuse -developers interested in just that - PyPy as a Python implementation. - -Digging a bit deeper you can find documentation which states the objectives of the -EU-funded part of the project. The EU project?s title is "PyPy" which is an acronym for -"Researching a Highly Flexible and Modular Language Platform and Implementing it by -Leveraging the Open Source Python Language and Community". The EU-project has -three objectives: one technical, one research-oriented and one methodology-oriented -objective. In short PyPy is about building an optimized compiler and interpreter purely -in Python, applying Aspect Oriented Programming and abstract interpretation techniques. -The methodology objective aims at showcasing the "sprint-driven development method" -being used by PyPy and you can view this paper as part of fullfilling the methodology -objective. +Due to the dual nature of the project even such a thing as objectives can get +complicated. If you, as a potential PyPy user, would visit out main developer +server codespeak you would find the following statement: + +"The PyPy project aims at producing a flexible and fast Python implementation. +The guiding idea is to translate a Python-level description of the Python +language itself to lower level languages. Rumors have it that the secret goal +is being faster-than-C which is nonsense, isn't it? more..." + +Codespeak housed the F/OSS project since it?s inception and it has been a +driving strategy to continue a look-and-feel of a purely F/OSS project in order +to not confuse developers interested in just that - PyPy as a Python +implementation. + +Digging a bit deeper you can find documentation which states the objectives of +the EU-funded part of the project. The EU project?s title is "PyPy" which is an +acronym for "Researching a Highly Flexible and Modular Language Platform and +Implementing it by Leveraging the Open Source Python Language and Community". +The EU-project has three objectives: one technical, one research-oriented and +one methodology-oriented objective. In short PyPy is about building an +optimized compiler and interpreter purely in Python, applying Aspect Oriented +Programming and abstract interpretation techniques. The methodology objective +aims at showcasing the "sprint-driven development method" being used by PyPy +and you can view this paper as part of fullfilling the methodology objective. Strategy: -~~~~~~~~~ ++++++++++ The strategy of the project is to leverage the community of PyPy and Python through open and transparent communication and working style. The challenge has @@ -124,45 +139,49 @@ strategy while also conforming to the actual requirements of the 6th Framework Programme. -The F/OSS part of PyPy has no budget tied to it and no formal organizational structure. -There are no resources tied to it other than the volunteers participating in the development -process, ranging from the core developers and architects behind PyPy to people from all -over the world, driven by a combination of professional need and personal interest in -Python language implementations such as PyPy and choosing to contribute to PyPy. There -is also a large group of students on PHD level participating and contributing, using their -areas of interest in PyPy as thesis material. - -It is difficult to estimate the amount of people involved in PyPy but we estimate that -ca 300-500 people "follow actively" the progress of the project - this might mean -reading emails, IRC logs and documention in some cases, asking questions and -sending bug reports in other cases.There are ca 50 people that have commit-rights -to the source code. The core group of developers consists of ca 10 people. - -The EU part of the project is organized through a consortium which consists of 8 -partners: DFKI (Germany), Ab Strakt (Sweden), Logilab (France), merlinux GmbH -(Germany), tismerysoft GmbH (Germany), Change Maker (Sweden) , Impara GmbH -(Germany) and Heinrich Heine Universit?t D?sseldorf (Germany) and 4 physical -person partners: Laura Creighton (Sweden), Richard Emslie (UK), -Eric Van Riet Paap (Netherlands) , Niklaus Haldiman (Switzerland). - -The project effort of work for the 2 years of funding consists -of 14 work-packages and in total 58 deliverables which are high-level functional -and non-functional requirements that were formulated in a proposal and form the +The F/OSS part of PyPy has no budget tied to it and no formal organizational +structure. There are no resources tied to it other than the volunteers +participating in the development process, ranging from the core developers and +architects behind PyPy to people from all over the world, driven by a +combination of professional need and personal interest in Python language +implementations such as PyPy and choosing to contribute to PyPy. There is also +a large group of students on PHD level participating and contributing, using +their areas of interest in PyPy as thesis material. + +It is difficult to estimate the amount of people involved in PyPy but we +estimate that ca 300-500 people "follow actively" the progress of the project - +this might mean reading emails, IRC logs and documention in some cases, asking +questions and sending bug reports in other cases.There are ca 50 people that +have commit-rights to the source code. The core group of developers consists of +ca 10 people. + +The EU part of the project is organized through a consortium which consists of +8 partners: DFKI (Germany), Ab Strakt (Sweden), Logilab (France), merlinux GmbH +(Germany), tismerysoft GmbH (Germany), Change Maker (Sweden) , Impara GmbH +(Germany) and Heinrich Heine Universit?t D?sseldorf (Germany) and 4 physical +person partners: Laura Creighton (Sweden), Richard Emslie (UK), Eric Van Riet +Paap (Netherlands) , Niklaus Haldiman (Switzerland). + +The project effort of work for the 2 years of funding consists of 14 +work-packages and in total 58 deliverables which are high-level functional and +non-functional requirements that were formulated in a proposal and form the "Description of Work" in the contract with the European Commission. The funding -recieved for this effort is 1.3 million euros. Of the core group of developers mentioned -above almost all of them (ca 10 people) are involved in some sense in the partner -companies and organizations of the PyPy consortium. +recieved for this effort is 1.3 million euros. Of the core group of developers +mentioned above almost all of them (ca 10 people) are involved in some sense in +the partner companies and organizations of the PyPy consortium. History: -~~~~~~~~ -The ideas behind PyPy started via discussions on european mailing-lists in the Python -community late 2002 by people that had been active in the Python community for -some time, core developers interested in language implementation. They based -the discussions and ideas partly on their experiences with developing and driving -some well-known projects in the Python community. They met up in February 2003 -at a "sprint", a one week working meeting,to draft their ideas and to start PyPy as -an Open Source project. The sprint facilities as well as travel, accommodation and -time was financed by all participants privately. +++++++++ + +The ideas behind PyPy started via discussions on european mailing-lists in the +Python community late 2002 by people that had been active in the Python +community for some time, core developers interested in language implementation. +They based the discussions and ideas partly on their experiences with +developing and driving some well-known projects in the Python community. They +met up in February 2003 at a "sprint", a one week working meeting,to draft +their ideas and to start PyPy as an Open Source project. The sprint facilities +as well as travel, accommodation and time was financed by all participants +privately. Mid 2003 the idea of trying to get EU-funding for the project was born. It became clear that the project had an arbitrarily large scale and that receiving @@ -179,15 +198,16 @@ had not previously been part of the development focus and both the EU and the parties involved had to adapt to the situation. -The contract with the EU was signed and the funded part of the project, with it?s -consortium structure, started 1 of December 2004. The funded part of the project -ends in November 2006. - -The first funded year of the project ended with a review in Brussels in January 2006, -hosted by the Commission, reviewing the 10 deliverables comprising the work of the -first year. All deliverables were accepted and based on recommendations by the external -reviewers the consortium and the Commission is now restructuring the volume of the -remaining the deliverables (although not changing the scope of the project). +The contract with the EU was signed and the funded part of the project, with +it?s consortium structure, started 1 of December 2004. The funded part of the +project ends in November 2006. + +The first funded year of the project ended with a review in Brussels in January +2006, hosted by the Commission, reviewing the 10 deliverables comprising the +work of the first year. All deliverables were accepted and based on +recommendations by the external reviewers the consortium and the Commission is +now restructuring the volume of the remaining the deliverables (although not +changing the scope of the project). Influencing factors: the F/OSS Python community culture ======================================================== @@ -195,102 +215,116 @@ The Python community -------------------- -Python is an Open Source language, published under an OSI approved open source license. -It was created by Guido van Rossum and is now one of the five most used languages in the world. -Due to the nature of the language there is a strong focus on glue and integration with other -languages such as C and Java etc. Other typical aspects of the Python community is that it -houses four large language implementations as separate projects that communicate and discuss -their experiences and approaches with each other. This intra-extra community focus and interest -have created a collaborative atmosphere with an open and transparent communication climate. The -key to a lively and working community is the people factor, as always and of course so for the -Python community as well. +Python is an Open Source language, published under an OSI approved open source +license. It was created by Guido van Rossum and is now one of the five most +used languages in the world. Due to the nature of the language there is a +strong focus on glue and integration with other languages such as C and Java +etc. Other typical aspects of the Python community is that it houses four large +language implementations as separate projects that communicate and discuss +their experiences and approaches with each other. This intra-extra community +focus and interest have created a collaborative atmosphere with an open and +transparent communication climate. The key to a lively and working community is +the people factor, as always and of course so for the Python community as well. The PyPy community ------------------ -The PyPy project is one of the four large language implementation projects in the Python community. -PyPy grew from the architectural experiences from previous successful Python projects and this -prior community experience was vital for the evolving of the PyPy community due to the established -trust in expert skills of the core developers starting PyPy - again the people factor.Thus making it easier -recruit people into the PyPy community. - -The PyPy project inherited the focus on collaborative approaches and open communication climate. -The nature of using sprints as a core technique as a way to kick-start the project as well as moving -the sprints to different locations as a strategy to encourage participation by meeting people locally -are clear examples of this. During the period of 2003-2004 6 sprints were arranged in various european -cities, hosted by universities and private persons, participation funded privately. The effect on the -evolving community was a stable subscriber participation on the development list of between 140-150 -people. After the EU-funding and the more systematic structure of sprinting every 6th week the -amount of subscribers went from ca 150 people to over 250 people. + +The PyPy project is one of the four large language implementation projects in +the Python community. PyPy grew from the architectural experiences from +previous successful Python projects and this prior community experience was +vital for the evolving of the PyPy community due to the established trust in +expert skills of the core developers starting PyPy - again the people +factor.Thus making it easier recruit people into the PyPy community. + +The PyPy project inherited the focus on collaborative approaches and open +communication climate. The nature of using sprints as a core technique as a +way to kick-start the project as well as moving the sprints to different +locations as a strategy to encourage participation by meeting people locally +are clear examples of this. During the period of 2003-2004 6 sprints were +arranged in various european cities, hosted by universities and private +persons, participation funded privately. The effect on the evolving community +was a stable subscriber participation on the development list of between +140-150 people. After the EU-funding and the more systematic structure of +sprinting every 6th week the amount of subscribers went from ca 150 people to +over 250 people. Supporting infrastructure -------------------------- -The amount of collaborative focus and open and transparent communication in -an open source community will manifest itself in the supporting infrastructure. -In PyPy version control is the primary means of providing a secure platform for -incremental development. In PyPy, Subversion is being used, covering both -program files and documentation. Several automated mailing lists makes sure that every -person involved receives instant notification on changes - supporting peer review on all levels. - -PyPy is also in some sense very much test-driven. PyPy is one of the -primary users of a separate F/OSS project called the py.test, tools for -automated testing with PyPy developers contributing improvements to py.test. -py.test contains a sophisticated system for running tests against the Python -Standard Library, with automatic selection of overriding tests in case there is -internally developed code that overrides the Python Standard Library - -important compliance features when the project is about language implementation. -There are also powerful mechanisms for disabling specific tests and for producing -useful traceback output. There are also automatically generated web pages that -show the status of all tests as per the latest checked in test results. - -The main communication channels between developers involved in PyPy is -to discuss over IRC (Internet-Relay-Chat) - open for all that are interested. -Several mailinglists for discussions and information is also used. Webpages, +The amount of collaborative focus and open and transparent communication in an +open source community will manifest itself in the supporting infrastructure. +In PyPy version control is the primary means of providing a secure platform for +incremental development. In PyPy, Subversion is being used, covering both +program files and documentation. Several automated mailing lists makes sure +that every person involved receives instant notification on changes - +supporting peer review on all levels. + +PyPy is also in some sense very much test-driven. PyPy is one of the primary +users of a separate F/OSS project called the py.test, tools for automated +testing with PyPy developers contributing improvements to py.test. py.test +contains a sophisticated system for running tests against the Python Standard +Library, with automatic selection of overriding tests in case there is +internally developed code that overrides the Python Standard Library - +important compliance features when the project is about language +implementation. There are also powerful mechanisms for disabling specific +tests and for producing useful traceback output. There are also automatically +generated web pages that show the status of all tests as per the latest checked +in test results. + +The main communication channels between developers involved in PyPy is to +discuss over IRC (Internet-Relay-Chat) - open for all that are interested. +Several mailinglists for discussions and information is also used. Webpages, documentation, tutorials, talks and papers etc are all available on the central -developer server for everyone.A very useful feature that really supports information -and communication (the author can attest to this from her own experience) are the public -email archives covering the key mailinglists - going back to the start of 2003. - -An extensive coding guide, published on codespeak.net (development website) -serves as an introduction to the set of specifications being used while coding PyPy. -The coding guide covers not only naming conventions but also -design, test and documentation guidelines. - -Now - all this infrastructure is being used in almost all larger open source projects and -quite a few of them are much more hierarchial and non-transparent in their communication. -In PyPy there is no hierarchy for recieving commit-rights. A newcomer to PyPy can instantly -recieve an account on the development server, with full commit rights to the version control -system. The reason why there are no constraints is that the process is very much -self-organized and managed by the developers from a social level -(peer review, code review, supporting communication channels, coaching, mentoring) and with -strong automated tools covering tests, versions and back ups covering the technical level. - -In a distributed and dispersed workstyle these two (social and technical) levels needs to be -consistent and support each other, discrepancies would be immediately noticed. As stated -before - the people factor is again evident and in order to encourage participation and -contribution there has to be trust as well as a supportive environment in order to manage a -virtual collaborative workspace. +developer server for everyone.A very useful feature that really supports +information and communication (the author can attest to this from her own +experience) are the public email archives covering the key mailinglists - going +back to the start of 2003. + +An extensive coding guide, published on codespeak.net (development website) +serves as an introduction to the set of specifications being used while coding +PyPy. The coding guide covers not only naming conventions but also design, +test and documentation guidelines. + +Now - all this infrastructure is being used in almost all larger open source +projects and quite a few of them are much more hierarchial and non-transparent +in their communication. In PyPy there is no hierarchy for recieving +commit-rights. A newcomer to PyPy can instantly recieve an account on the +development server, with full commit rights to the version control system. The +reason why there are no constraints is that the process is very much +self-organized and managed by the developers from a social level (peer review, +code review, supporting communication channels, coaching, mentoring) and with +strong automated tools covering tests, versions and back ups covering the +technical level. + +In a distributed and dispersed workstyle these two (social and technical) +levels needs to be consistent and support each other, discrepancies would be +immediately noticed. As stated before - the people factor is again evident and +in order to encourage participation and contribution there has to be trust as +well as a supportive environment in order to manage a virtual collaborative +workspace. Supporting practices -------------------- -Another good example of the collaborative nature of the Python community is the way -which the various projects share best practices. Core developers in the PyPy project picked -up the practice of synchronization meetings as a powerful way of supporting distributed and -dispersed development, implemented by Canonical. - -Sync-meetings are weekly short coordination meetings between developers, open to -all developers active in the PyPy community, usually but not necessarily involving aspects -of EU-funded work on deliverables. These 30 minute IRC-meetings serve a weekly -synchronisation for regular discussions and integration of ongoing work. Meetings are -prepared with an agenda sent out to pypy-dev and minutes are distributed on pypy-dev and -archived in the repository with publicly accessible links.Preparing, managing and documenting -the meetings is rotated between active developers and is self-organized as well. - -Sync-meetings have proven to be a very good complement to a process in which the project -sprints every 6th week. Sync-meetings keep cohesion as well as a team focus-and-feel for -the dispersed workstyle between sprints. +Another good example of the collaborative nature of the Python community is the +way which the various projects share best practices. Core developers in the +PyPy project picked up the practice of synchronization meetings as a powerful +way of supporting distributed and dispersed development, implemented by +Canonical. + +Sync-meetings are weekly short coordination meetings between developers, open +to all developers active in the PyPy community, usually but not necessarily +involving aspects of EU-funded work on deliverables. These 30 minute +IRC-meetings serve a weekly synchronisation for regular discussions and +integration of ongoing work. Meetings are prepared with an agenda sent out to +pypy-dev and minutes are distributed on pypy-dev and archived in the repository +with publicly accessible links.Preparing, managing and documenting the meetings +is rotated between active developers and is self-organized as well. + +Sync-meetings have proven to be a very good complement to a process in which +the project sprints every 6th week. Sync-meetings keep cohesion as well as a +team focus-and-feel for the dispersed workstyle between sprints. Influencing factors: agile practices in PyPy ============================================ @@ -310,59 +344,62 @@ method as it is used in the Python community says the following about how they evolved the method during 2001 and 2002: -"The motivation was to begin using as much of XP as would fit to accelerate Zope3 -development. Given the different development culture of the Zope community -(framework-centric, distributed, no "business user" present), some of the XP mantras /practices -couldn't be done directly. We decided to try to do "as much XP as possible" for short, -highly-focused sessions, with all active committers colocated." +"The motivation was to begin using as much of XP as would fit to accelerate +Zope3 development. Given the different development culture of the Zope +community (framework-centric, distributed, no "business user" present), some of +the XP mantras /practices couldn't be done directly. We decided to try to do +"as much XP as possible" for short, highly-focused sessions, with all active +committers colocated." -Zope Corporation as well as other Python projects such as PyPy have seen -that sprints have goals beyond the creation of software: +Zope Corporation as well as other Python projects such as PyPy have seen that +sprints have goals beyond the creation of software: - It helped to evolve the community through participation and hands-on contact -with the core developers. + with the core developers. -- It is a live training session not only in producing code but also in the development -methods being used (TDD, pairprogramming etc, the sprint method in itself). +- It is a live training session not only in producing code but also in the + development methods being used (TDD, pairprogramming etc, the sprint method + in itself). + +- It supports activities such as design decisions and high-level requirements + discussions, creating cohesion and understanding as well as minimizing risks + with dispersed/distributed work where these kind of activities can be really + difficult to manage. -- It supports activities such as design decisions and high-level requirements discussions, -creating cohesion and understanding as well as minimizing risks with dispersed/distributed -work where these kind of activities can be really difficult to manage. - -The reason for naming the method sprinting, not at all connected to Scrum and +The reason for naming the method sprinting, not at all connected to Scrum and the usage of sprints in that context, according to Tres Seaver is: -"... because of the fact that we weren't doing XP in its proper sense, which is -more like running a long-distance race, where pacing oneself is critical. -Instead, we were pushing as fast as possible in order to maximize the benefit of limited -face time. Of all the XP practices, the one we gave shortest shrift to -is "no overtime": as sprints often go far into the evening (or even -the wee hours of the morning." - -The sprint method, as well as key aspects of F/OSS supportive infrastructure and -practices was established within the project before PyPy recieved it?s EU-funding. -Thus, in the proposal,we put much emphasis on the methodology in itself when -designing the consortium level process. Examples of how this was done was that -we created a methodology objective, specific deliverables regarding documentation -of the sprint-driven methodology as well as designing a process during the 2 years -of funding in which the project and the developers sprints every 6th week. This was -taken into account when estimating the budget, adding costs for travel and -accommodation for all partner organizations - covering 14 sprints during the 2 years. -So far during the funded part of the project we have organized 10 sprints - successful -sprints from both a development, recruiting, dissemination and networking aspects. -Another important fact is that the sprints are organized by the developers and as such is -another good example of the collaborative manner of the culture of the project and the -community. +"... because of the fact that we weren't doing XP in its proper sense, which is +more like running a long-distance race, where pacing oneself is critical. +Instead, we were pushing as fast as possible in order to maximize the benefit +of limited face time. Of all the XP practices, the one we gave shortest shrift +to is "no overtime": as sprints often go far into the evening (or even the wee +hours of the morning." + +The sprint method, as well as key aspects of F/OSS supportive infrastructure +and practices was established within the project before PyPy recieved it?s +EU-funding. Thus, in the proposal,we put much emphasis on the methodology in +itself when designing the consortium level process. Examples of how this was +done was that we created a methodology objective, specific deliverables +regarding documentation of the sprint-driven methodology as well as designing a +process during the 2 years of funding in which the project and the developers +sprints every 6th week. This was taken into account when estimating the budget, +adding costs for travel and accommodation for all partner organizations - +covering 14 sprints during the 2 years. So far during the funded part of the +project we have organized 10 sprints - successful sprints from both a +development, recruiting, dissemination and networking aspects. Another +important fact is that the sprints are organized by the developers and as such +is another good example of the collaborative manner of the culture of the +project and the community. Why did PyPy choose sprinting as a key technique? It is a method that fits -distributed teams well because it gets the team focused around visible +distributed teams well because it gets the team focused around visible challenging goals while working collarobatively (pair-programming, status -meetings, discussions etc) as well as accelerated (short increments and -tasks, "doing" and testing instead of long startups of planning and -requirement gathering, continuous integration). This means that most of -the time a sprint is a great way of getting results and getting new -people aquainted - a good method for dissemination of knowledge and -learning within the team. +meetings, discussions etc) as well as accelerated (short increments and tasks, +"doing" and testing instead of long startups of planning and requirement +gathering, continuous integration). This means that most of the time a sprint +is a great way of getting results and getting new people aquainted - a good +method for dissemination of knowledge and learning within the team. A key insight, worthwhile for other EU-projects to ponder, is how an agile process like sprinting is much more suited for creative work between groups of @@ -377,43 +414,50 @@ Consortium structure -------------------- -Key requirements regarding organizational structures of an Framework Programme 6 -EU-project are: +Key requirements regarding organizational structures of an Framework Programme +6 EU-project are: + - a consortium of partners performing the work described in the contract -- a project co-ordinator managing contract administration and communication -between consortium and the Commission -- a project manager, responsible for the project reaching it?s goals within the -timeframe and budget -The challenge was to design a project process that created a minimal amount of +- a project co-ordinator managing contract administration and communication + between consortium and the Commission + +- a project manager, responsible for the project reaching it?s goals within the + timeframe and budget + +The challenge was to design a project process that created a minimal amount of changes to the structure being in use in the F/OSS project. It was especially -important to maintain an open and transparent communication, even for decision on -consortium level and such. There was a fear of the EU-project adding "top-down" -structures on the F/OSS work and on the core developers instigating the project. - -We identified a minimalistic approach of management roles (project co-ordinator, project -manager, assistant project manager) and created a management team to make sure -that there was collaboration between these roles. Although the responsibility rested on -the different management roles and the management team the strategy implemented was to -delegate as much as possible of the responsibilities and decision-making to the core developers. +important to maintain an open and transparent communication, even for decision +on consortium level and such. There was a fear of the EU-project adding +"top-down" structures on the F/OSS work and on the core developers instigating +the project. + +We identified a minimalistic approach of management roles (project +co-ordinator, project manager, assistant project manager) and created a +management team to make sure that there was collaboration between these roles. +Although the responsibility rested on the different management roles and the +management team the strategy implemented was to delegate as much as possible of +the responsibilities and decision-making to the core developers. The strategy was to keep "conceptual integrity" (Brooks) of the vision and the idea in the hands of the core developers. A somewhat negative result was the -added workload and responsibility on developers regarding EU related work. -The core developers were organized into a technical board, responsible for planning +added workload and responsibility on developers regarding EU related work. The +core developers were organized into a technical board, responsible for planning and coordinating the development work between the partners. -This structure was the most difficult to design and implement due to the very different nature -of it?s purpose compared to the collaborative, self-organized nature of the F/OSS project - -again it succeeded the way it has because of the core developers acting as an interface between -the developer group and the consortium level work - again we see the trust aspect and the people -factor in play. - -Sprints were budgeted for and designed into the process, together with a timeplan -for all deliverables. The project was divided into three different phases, depending -on the nature of the workflow. In that sense you could describe the EU-part of the project -as a fixed-contract style of work, but with timeplan, deliverables and work package descriptions -on a high-level, not broken down into more granular tasks. +This structure was the most difficult to design and implement due to the very +different nature of it?s purpose compared to the collaborative, self-organized +nature of the F/OSS project - again it succeeded the way it has because of the +core developers acting as an interface between the developer group and the +consortium level work - again we see the trust aspect and the people factor in +play. + +Sprints were budgeted for and designed into the process, together with a +timeplan for all deliverables. The project was divided into three different +phases, depending on the nature of the workflow. In that sense you could +describe the EU-part of the project as a fixed-contract style of work, but with +timeplan, deliverables and work package descriptions on a high-level, not +broken down into more granular tasks. Resource tracking and reporting ------------------------------- @@ -421,50 +465,58 @@ The nature of reporting on a consortium level is very much focused on the costs incurred by each partner compared to budget, by the consortium on a specific workpackage and of the consortium overall. The consortium is free to reallocate -budgeted manmonth funding between partners during the project. The project reports -costs per period - PyPy have two periods. +budgeted manmonth funding between partners during the project. The project +reports costs per period - PyPy have two periods. -Again - the need for open and transparent communication together with a collaborative -climate created the need to have what we believe a unique view on cost reporting -within the project. In PyPy all timesheets are gathered on a monthly basis and stored in -central repository, accessible for all consortium partners (managers and developers alike). -Cost claims from all partners are gathered on a six month basis. This data helps the -management board and technical board to assess the status of work. - -Templates for timesheets, costs claims, resource tracking tools etc are created in open -formats and all data is stored under the same version control that we use for the source -code. All reports are produced with docutils/ReST format which together with automated -mailinglists for covering updates in the version control repositories allows for collaborate -peer-reviewing regarding the EU-level of reports. Again the strategy was to use the same -tools and practises on consortium level work as is used in the development process. -Interesting to note is that the technical reports written for the Commission regarding certain -deliverables and progress have also been a great help towards the community who also have -free access to these reports and view them as extra, although peculiar formated, documentation. +Again - the need for open and transparent communication together with a +collaborative climate created the need to have what we believe a unique view on +cost reporting within the project. In PyPy all timesheets are gathered on a +monthly basis and stored in central repository, accessible for all consortium +partners (managers and developers alike). Cost claims from all partners are +gathered on a six month basis. This data helps the management board and +technical board to assess the status of work. + +Templates for timesheets, costs claims, resource tracking tools etc are created +in open formats and all data is stored under the same version control that we +use for the source code. All reports are produced with docutils/ReST format +which together with automated mailinglists for covering updates in the version +control repositories allows for collaborate peer-reviewing regarding the +EU-level of reports. Again the strategy was to use the same tools and practises +on consortium level work as is used in the development process. Interesting to +note is that the technical reports written for the Commission regarding certain +deliverables and progress have also been a great help towards the community who +also have free access to these reports and view them as extra, although +peculiar formated, documentation. Communication and documentation ------------------------------- -All documentation and supporting communication infrastructure is hosted on the same developer -server as the source code, covered by the same version control system. Only a few repositories -are not public available (such as the resource tracking repositories) - but they are fully accessible -for everyone employed by a partner organization. - -The communication infrastructure being used on the consortium level of work mirrors that of the -development work - having years of experience on the distributed workstyle. In the case of PyPY -there are mailinglists as well as IRC channels for consortium level work. We even implemented a -procedure in our internal consortium agreement to allow for virtual meetings for decisions in -the consortium. So far this have been the primary meeting form and it has worked well as a channel -for making decisions. IRC-logs and minutes support the procedure. In some cases decisions have also -been made via email on the consortium mailinglist. - -Although not the primary focus it is also useful to have the regular sprints to coordinate specific issues -between some partners or between all partners, have physical meetings and discussions between -the management team and the technical board etc. - -Our funding have also resulted in the possibility to have a more unorthodox documention - the project -have experimented in filming sprints to show the development method as well as filming talks and -discussion. Our film material is planned to be released before summer 2006. +All documentation and supporting communication infrastructure is hosted on the +same developer server as the source code, covered by the same version control +system. Only a few repositories are not public available (such as the resource +tracking repositories) - but they are fully accessible for everyone employed by +a partner organization. + +The communication infrastructure being used on the consortium level of work +mirrors that of the development work - having years of experience on the +distributed workstyle. In the case of PyPY there are mailinglists as well as +IRC channels for consortium level work. We even implemented a procedure in our +internal consortium agreement to allow for virtual meetings for decisions in +the consortium. So far this have been the primary meeting form and it has +worked well as a channel for making decisions. IRC-logs and minutes support the +procedure. In some cases decisions have also been made via email on the +consortium mailinglist. + +Although not the primary focus it is also useful to have the regular sprints to +coordinate specific issues between some partners or between all partners, have +physical meetings and discussions between the management team and the technical +board etc. + +Our funding have also resulted in the possibility to have a more unorthodox +documention - the project have experimented in filming sprints to show the +development method as well as filming talks and discussion. Our film material +is planned to be released before summer 2006. Troubles in Paradise:striking a balance ======================================= @@ -472,76 +524,83 @@ Developer driven versus formal project structure ------------------------------------------------ -The fear of a top-down, hierarchial decision process of the consortium was a justified one. -It is interesting for us to note that now, having the experience and more contractual -overview to note that there is nothing in the requirements from the Commission that forces -a project to a more traditional and strict project process. It is mostly a question of the -experience and customs of the partner companies. In that sense there was much flexibility -in designing a process that allowed for a developer driven process regarding not only software -development but also sprint administration and planning as well as consortium work. - -The majority of the partners on key roles in the consortium organization had been working -together since before the funding, procedures and best practises had been tried out. The -results from the first year showed that a minimalistic path could be identified and that the -important work would be to review and adjust the process when it did not support the work -any more, or new situations arose that we had not planned for (and that did happen!). - -Already year two has another look-and-feel to it on a consortium level when it comes to -how the management team and the technical board works, because of the different -nature of work in year two. +The fear of a top-down, hierarchial decision process of the consortium was a +justified one. It is interesting for us to note that now, having the +experience and more contractual overview to note that there is nothing in the +requirements from the Commission that forces a project to a more traditional +and strict project process. It is mostly a question of the experience and +customs of the partner companies. In that sense there was much flexibility in +designing a process that allowed for a developer driven process regarding not +only software development but also sprint administration and planning as well +as consortium work. + +The majority of the partners on key roles in the consortium organization had +been working together since before the funding, procedures and best practises +had been tried out. The results from the first year showed that a minimalistic +path could be identified and that the important work would be to review and +adjust the process when it did not support the work any more, or new situations +arose that we had not planned for (and that did happen!). + +Already year two has another look-and-feel to it on a consortium level when it +comes to how the management team and the technical board works, because of the +different nature of work in year two. Agile strategies versus formal EU-contractual requirements ---------------------------------------------------------- -Our main agile practise, sprint-driven development, was successfully integrated into -the formal contractual requirements, allowing for the same free-floating agile process -of self organizing and decision making as existed before the funding, but with a more -systematic and documented style. - -But here is also our biggest failure, the main "un-agile" aspect of the entire project having -a large negative effect not only on the EU-part of the project but also on the community. -We had planned for a process that kept an "open-door" policy that allowed us to fund -non-consortium persons from the community to attend sprints. The budget was allocated, -the procedure within the sprint context of handling more newcomers were known to us - the -main showstopper was that PyPy sprint funding did not fit within the customs and practices -of contracts for cost claims in the Commission. - -Every time we want to encourage participation and fund people to participate in sprints -and contribute the procedure now is that they have to join the consortium as a full -partner - but as a "physical person".This creates the need for a contractual amendment which -adds administrative work to the project as well as for the persons in question. A too blunt -instrument and today we still do not have a working solution to this problem. It is an -unfortunate example on how the influencing factor of F/OSS, agile practices and -EU-funding collides and creates negative impact on the project. +Our main agile practise, sprint-driven development, was successfully integrated +into the formal contractual requirements, allowing for the same free-floating +agile process of self organizing and decision making as existed before the +funding, but with a more systematic and documented style. + +But here is also our biggest failure, the main "un-agile" aspect of the entire +project having a large negative effect not only on the EU-part of the project +but also on the community. We had planned for a process that kept an +"open-door" policy that allowed us to fund non-consortium persons from the +community to attend sprints. The budget was allocated, the procedure within the +sprint context of handling more newcomers were known to us - the main +showstopper was that PyPy sprint funding did not fit within the customs and +practices of contracts for cost claims in the Commission. + +Every time we want to encourage participation and fund people to participate in +sprints and contribute the procedure now is that they have to join the +consortium as a full partner - but as a "physical person".This creates the need +for a contractual amendment which adds administrative work to the project as +well as for the persons in question. A too blunt instrument and today we still +do not have a working solution to this problem. It is an unfortunate example on +how the influencing factor of F/OSS, agile practices and EU-funding collides +and creates negative impact on the project. F/OSS community versus hierarchies for "conceptual integrity" ------------------------------------------------------------- There are many examples of F/OSS projects and communities that have dried out -because of the fear of the architects to allow the contributors to fully participate -and also influence features and vision of the software. In PyPy this challenge comes -twofold. Not only is there a challenge to let the core developers keep "conceptual -integrity" while also allowing the community to influence the direction and features of -the software. There is also the consortium level of work in which the core developers -could fear to "loose" the mandate of driving the architectural and design work. And -yet another layer of risk and complexity would be if the consortium level would -"shut the door" on the community, enforcing a more closed development process. +because of the fear of the architects to allow the contributors to fully +participate and also influence features and vision of the software. In PyPy +this challenge comes twofold. Not only is there a challenge to let the core +developers keep "conceptual integrity" while also allowing the community to +influence the direction and features of the software. There is also the +consortium level of work in which the core developers could fear to "loose" the +mandate of driving the architectural and design work. And yet another layer of +risk and complexity would be if the consortium level would "shut the door" on +the community, enforcing a more closed development process. -As in many cases - being risk aware is the first step to mitigate. Because the +As in many cases - being risk aware is the first step to mitigate. Because the project is so deeply rooted in the F/OSS Python community, with it?s specific -culture and climate, and because so many people involved in the core work -on both the development and consortium level also shared this background they -took great pains to avoid situations like this to happen. In fact, what we have realized -only some months ago is that there is another risk, already partly having effect on -the community. Because of the funding the development process is progressing much -more rapidly in PyPy than more normal F/OSS projects. The speed and the dramatically -increasing learning curve could make members more passive because they do not -have the time to follow full-time IRC discussions, postings on mailinglists and the actual -source code and increasing test suites. - -This is a challenge and it is the focus of the developer group to try to distill and package -information in order to help people to better navigate the progress. +culture and climate, and because so many people involved in the core work on +both the development and consortium level also shared this background they took +great pains to avoid situations like this to happen. In fact, what we have +realized only some months ago is that there is another risk, already partly +having effect on the community. Because of the funding the development process +is progressing much more rapidly in PyPy than more normal F/OSS projects. The +speed and the dramatically increasing learning curve could make members more +passive because they do not have the time to follow full-time IRC discussions, +postings on mailinglists and the actual source code and increasing test suites. + +This is a challenge and it is the focus of the developer group to try to +distill and package information in order to help people to better navigate the +progress. Conclusion ========== @@ -553,7 +612,8 @@ We believe so. The one clear dominating factor to make all this succeed is, as always, the people factor, the CRACK performers as Boehm and Turner calls them -("Collaborative, Representative, Authorized, Committed, Knowledgeable"). . +("Collaborative, Representative, Authorized, Committed, Knowledgeable"). +. The core developers of the PyPy project had the right mix of various skills in order to succeed in setting up a hybrid environment - enabling them to work From cfbolz at codespeak.net Tue May 2 15:36:12 2006 From: cfbolz at codespeak.net (cfbolz at codespeak.net) Date: Tue, 2 May 2006 15:36:12 +0200 (CEST) Subject: [pypy-svn] r26668 - pypy/extradoc/talk/agile2006 Message-ID: <20060502133612.2AF0E100A7@code0.codespeak.net> Author: cfbolz Date: Tue May 2 15:36:11 2006 New Revision: 26668 Modified: pypy/extradoc/talk/agile2006/draftpaper_agile2006.pdf Log: add pdf version which should be close to IEEE requirements Modified: pypy/extradoc/talk/agile2006/draftpaper_agile2006.pdf ============================================================================== Binary files. No diff available. From ale at codespeak.net Tue May 2 17:18:48 2006 From: ale at codespeak.net (ale at codespeak.net) Date: Tue, 2 May 2006 17:18:48 +0200 (CEST) Subject: [pypy-svn] r26674 - pypy/dist/pypy/module/_socket Message-ID: <20060502151848.4BAEB100AC@code0.codespeak.net> Author: ale Date: Tue May 2 17:18:47 2006 New Revision: 26674 Modified: pypy/dist/pypy/module/_socket/interp_socket.py Log: small progress in translating _socket Modified: pypy/dist/pypy/module/_socket/interp_socket.py ============================================================================== --- pypy/dist/pypy/module/_socket/interp_socket.py (original) +++ pypy/dist/pypy/module/_socket/interp_socket.py Tue May 2 17:18:47 2006 @@ -8,6 +8,7 @@ from pypy.rpython.rctypes.socketmodule import ctypes_socket as _c import ctypes from pypy.rpython.rctypes import implementation as rctypes_implemetation +from pypy.rpython.rarithemetic import intmask import errno IPV4_ADDRESS_SIZE = 4 @@ -606,12 +607,12 @@ if retval != 0: raise w_get_socketgaierror(space, None, retval) - try: - result = [] - next = res - while next: - info = next.contents - next = info.ai_next + result = [] + next = res + while next: + info = next.contents + next = info.ai_next + try: w_family = space.wrap(info.ai_family) w_socktype = space.wrap(info.ai_socktype) w_proto = space.wrap(info.ai_protocol) @@ -620,13 +621,16 @@ else: w_canonname = space.wrap('') w_addr = w_makesockaddr(space, - _c.cast(info.ai_addr, _c.sockaddr_ptr), - info.ai_addrlen, info.ai_protocol) + _c.cast(info.ai_addr, _c.sockaddr_ptr), + info.ai_addrlen, info.ai_protocol) result.append(space.newtuple([w_family, w_socktype, w_proto, - w_canonname, w_addr])) - return space.newlist(result) - finally: - _c.freeaddrinfo(res) + w_canonname, w_addr])) + except: + _c.freeaddrinfo(res) + raise + res = space.newlist(result) + _c.freeaddrinfo(res) + return res getaddrinfo.unwrap_spec = [ObjSpace, W_Root, W_Root, int, int, int, int] def getnameinfo(space, w_sockaddr, flags): @@ -781,7 +785,7 @@ raise w_get_socketgaierror(space, None, retval) addrinfo = res.contents addrlen = addrinfo.ai_addrlen - caddr_buf = ctypes.create_string_buffer(int(addrlen)) # XXX forcing a long to an int + caddr_buf = ctypes.create_string_buffer(intmask(addrlen)) # XXX forcing a long to an int _c.memcpy(caddr_buf, addrinfo.ai_addr, addrlen) sockaddr_ptr = ctypes.cast(caddr_buf, _c.sockaddr_ptr) @@ -985,9 +989,10 @@ """ buf = _c.create_string_buffer(buffersize) sockaddr = _c.sockaddr() + sockaddr_size = _c.socklen_t() read_bytes = _c.recvfrom(self.fd, buf, buffersize, flags, - _c.pointer(sockaddr), _c.sockaddr_size) - w_addr = w_makesockaddr(space, _c.pointer(sockaddr), _c.sockaddr_size, self.proto) + _c.pointer(sockaddr), _c.pointer(sockaddr_size)) + w_addr = w_makesockaddr(space, _c.pointer(sockaddr), sockaddr_size.value, self.proto) if read_bytes < 0: raise w_get_socketerror(space, None, _c.geterrno()) return space.newtuple([space.wrap(buf[:read_bytes]), w_addr]) @@ -1059,12 +1064,14 @@ """ if space.is_true(space.isinstance(w_value, space.w_str)): strvalue = space.str_w(w_value) + size = _c.socklen_t(len(strvalue)) _c.socketsetsockopt(self.fd, level, option, strvalue, - len(strvalue)) + size) else: intvalue = ctypes.c_int(space.int_w(w_value)) + size = _c.socklen_t(_c.c_int_size) _c.socketsetsockopt(self.fd, level, option, _c.pointer(intvalue), - _c.c_int_size) + size) setsockopt.unwrap_spec = ['self', ObjSpace, int, int, W_Root] def gettimeout(self, space): From ale at codespeak.net Tue May 2 17:32:35 2006 From: ale at codespeak.net (ale at codespeak.net) Date: Tue, 2 May 2006 17:32:35 +0200 (CEST) Subject: [pypy-svn] r26675 - pypy/dist/pypy/module/_socket Message-ID: <20060502153235.BAD4E10094@code0.codespeak.net> Author: ale Date: Tue May 2 17:32:35 2006 New Revision: 26675 Modified: pypy/dist/pypy/module/_socket/interp_socket.py Log: ups didnt run the tests first Modified: pypy/dist/pypy/module/_socket/interp_socket.py ============================================================================== --- pypy/dist/pypy/module/_socket/interp_socket.py (original) +++ pypy/dist/pypy/module/_socket/interp_socket.py Tue May 2 17:32:35 2006 @@ -8,7 +8,7 @@ from pypy.rpython.rctypes.socketmodule import ctypes_socket as _c import ctypes from pypy.rpython.rctypes import implementation as rctypes_implemetation -from pypy.rpython.rarithemetic import intmask +from pypy.rpython.rarithmetic import intmask import errno IPV4_ADDRESS_SIZE = 4 From arigo at codespeak.net Tue May 2 17:41:20 2006 From: arigo at codespeak.net (arigo at codespeak.net) Date: Tue, 2 May 2006 17:41:20 +0200 (CEST) Subject: [pypy-svn] r26676 - pypy/dist/pypy/rpython/rctypes/test Message-ID: <20060502154120.79DAF100AC@code0.codespeak.net> Author: arigo Date: Tue May 2 17:41:19 2006 New Revision: 26676 Modified: pypy/dist/pypy/rpython/rctypes/test/test_ctypes.py Log: Remove the unneeded try:finally: as I realized that objspace/cpy/capi gets different FuncPtr objects anyway. Modified: pypy/dist/pypy/rpython/rctypes/test/test_ctypes.py ============================================================================== --- pypy/dist/pypy/rpython/rctypes/test/test_ctypes.py (original) +++ pypy/dist/pypy/rpython/rctypes/test/test_ctypes.py Tue May 2 17:41:19 2006 @@ -175,32 +175,24 @@ def test_pythonapi(): PyInt_AsLong = pythonapi.PyInt_AsLong - saved = PyInt_AsLong.__dict__.copy() - try: - PyInt_AsLong.argtypes = [py_object] - PyInt_AsLong.restype = c_long - assert PyInt_AsLong(py_object(17L)) == 17 - py.test.raises(TypeError, "PyInt_AsLong(py_object('hello'))") - finally: - PyInt_AsLong.__dict__ = saved + PyInt_AsLong.argtypes = [py_object] + PyInt_AsLong.restype = c_long + assert PyInt_AsLong(py_object(17L)) == 17 + py.test.raises(TypeError, "PyInt_AsLong(py_object('hello'))") def test_py_object_subclass(): PyInt_FromLong = pythonapi.PyInt_FromLong - saved = PyInt_FromLong.__dict__.copy() - try: - # automatic unwrapping of the py_object result - PyInt_FromLong.argtypes = [c_long] - PyInt_FromLong.restype = py_object - assert isinstance(PyInt_FromLong(17), int) - - # but not if we subclass it... - class W_Object(py_object): - pass - PyInt_FromLong.argtypes = [c_long] - PyInt_FromLong.restype = W_Object - assert isinstance(PyInt_FromLong(17), W_Object) - finally: - PyInt_FromLong.__dict__ = saved + # automatic unwrapping of the py_object result + PyInt_FromLong.argtypes = [c_long] + PyInt_FromLong.restype = py_object + assert isinstance(PyInt_FromLong(17), int) + + # but not if we subclass it... + class W_Object(py_object): + pass + PyInt_FromLong.argtypes = [c_long] + PyInt_FromLong.restype = W_Object + assert isinstance(PyInt_FromLong(17), W_Object) def test_sizeof(): x = create_string_buffer(117) @@ -210,23 +202,19 @@ def test_convert_pointers(): PyString_FromString = pythonapi.PyString_FromString - saved = PyString_FromString.__dict__.copy() - try: - PyString_FromString.restype = py_object - - # automatic conversions to c_char_p - PyString_FromString.argtypes = [c_char_p] - assert PyString_FromString("hello") == "hello" - assert PyString_FromString(c_char_p("hello")) == "hello" - assert PyString_FromString((c_char * 6)(*"hello")) == "hello" - assert PyString_FromString(create_string_buffer("hello")) == "hello" - - # automatic conversions to c_void_p - PyString_FromString.argtypes = [c_void_p] - assert PyString_FromString("hello") == "hello" - assert PyString_FromString(c_char_p("hello")) == "hello" - assert PyString_FromString((c_char * 6)(*"hello")) == "hello" - assert PyString_FromString((c_byte * 6)(104,101,108,108,111)) =="hello" - assert PyString_FromString(create_string_buffer("hello")) == "hello" - finally: - PyString_FromString.__dict__ = saved + PyString_FromString.restype = py_object + + # automatic conversions to c_char_p + PyString_FromString.argtypes = [c_char_p] + assert PyString_FromString("hello") == "hello" + assert PyString_FromString(c_char_p("hello")) == "hello" + assert PyString_FromString((c_char * 6)(*"hello")) == "hello" + assert PyString_FromString(create_string_buffer("hello")) == "hello" + + # automatic conversions to c_void_p + PyString_FromString.argtypes = [c_void_p] + assert PyString_FromString("hello") == "hello" + assert PyString_FromString(c_char_p("hello")) == "hello" + assert PyString_FromString((c_char * 6)(*"hello")) == "hello" + assert PyString_FromString((c_byte * 6)(104,101,108,108,111)) =="hello" + assert PyString_FromString(create_string_buffer("hello")) == "hello" From arigo at codespeak.net Tue May 2 17:50:15 2006 From: arigo at codespeak.net (arigo at codespeak.net) Date: Tue, 2 May 2006 17:50:15 +0200 (CEST) Subject: [pypy-svn] r26678 - in pypy/dist/pypy: objspace/cpy objspace/cpy/test rpython/rctypes rpython/rctypes/test Message-ID: <20060502155015.1794B100BF@code0.codespeak.net> Author: arigo Date: Tue May 2 17:50:12 2006 New Revision: 26678 Modified: pypy/dist/pypy/objspace/cpy/ann_policy.py pypy/dist/pypy/objspace/cpy/capi.py pypy/dist/pypy/objspace/cpy/ctypes_base.py pypy/dist/pypy/objspace/cpy/objspace.py pypy/dist/pypy/objspace/cpy/test/test_compile.py pypy/dist/pypy/objspace/cpy/wrappable.py pypy/dist/pypy/rpython/rctypes/afunc.py pypy/dist/pypy/rpython/rctypes/test/test_rfunc.py Log: Support exceptions in the CPyObjSpace, both when running on top of CPython and when translated. When translated, an extra call to rctypes_pyerrchecker() is inserted, which does the PyErr_Occurred() and PyErr_Fetch() magic to turn it into an OperationError. With some hacks the existing trampoline() function is able to do the converse: turn an OperationError into the CPython exception it contains. Modified: pypy/dist/pypy/objspace/cpy/ann_policy.py ============================================================================== --- pypy/dist/pypy/objspace/cpy/ann_policy.py (original) +++ pypy/dist/pypy/objspace/cpy/ann_policy.py Tue May 2 17:50:12 2006 @@ -2,7 +2,7 @@ from pypy.annotation.pairtype import pair from pypy.annotation import model as annmodel from pypy.interpreter.error import OperationError -from pypy.objspace.cpy.ctypes_base import W_Object +from pypy.objspace.cpy.ctypes_base import W_Object, rctypes_pyerrchecker class CPyAnnotatorPolicy(PyPyAnnotatorPolicy): """Annotation policy to compile CPython extension modules with @@ -30,8 +30,15 @@ # could have found new objects # force w_type, w_value attributes into the OperationError class - classdef = annotator.bookkeeper.getuniqueclassdef(OperationError) + bk = annotator.bookkeeper + classdef = bk.getuniqueclassdef(OperationError) s_instance = annmodel.SomeInstance(classdef=classdef) for name in ['w_type', 'w_value']: - s_instance.setattr(annotator.bookkeeper.immutablevalue(name), - annotator.bookkeeper.valueoftype(W_Object)) + s_instance.setattr(bk.immutablevalue(name), + bk.valueoftype(W_Object)) + + # annotate rctypes_pyerrchecker() + uniquekey = rctypes_pyerrchecker + s_pyerrchecker = bk.immutablevalue(rctypes_pyerrchecker) + s_result = bk.emulate_pbc_call(uniquekey, s_pyerrchecker, []) + assert annmodel.s_None.contains(s_result) Modified: pypy/dist/pypy/objspace/cpy/capi.py ============================================================================== --- pypy/dist/pypy/objspace/cpy/capi.py (original) +++ pypy/dist/pypy/objspace/cpy/capi.py Tue May 2 17:50:12 2006 @@ -86,6 +86,14 @@ PyIter_Next.argtypes = [W_Object] PyIter_Next.restype = W_Object +PyObject_IsTrue = cpyapi.PyObject_IsTrue +PyObject_IsTrue.argtypes = [W_Object] +PyObject_IsTrue.restype = c_int + +PyObject_Type = cpyapi.PyObject_Type +PyObject_Type.argtypes = [W_Object] +PyObject_Type.restype = W_Object + ########################################################### # ____________________ Number Protocol ____________________ @@ -111,6 +119,14 @@ PySequence_SetItem.restype = c_int +######################################################## +# ____________________ Type Objects ____________________ + +PyType_IsSubtype = cpyapi.PyType_IsSubtype +PyType_IsSubtype.argtypes = [W_Object, W_Object] +PyType_IsSubtype.restype = c_int + + ########################################################### # ____________________ Numeric Objects ____________________ @@ -178,13 +194,6 @@ PyImport_ImportModule.argtypes = [c_char_p] PyImport_ImportModule.restype = W_Object -# "RAW" because it comes from pythonapi instead of cpyapi -# which makes it raise the set exception directly instead -# of wrapping it into an OperationError -RAW_PyErr_SetObject = pythonapi.PyErr_SetObject -RAW_PyErr_SetObject.argtypes = [W_Object, W_Object] -RAW_PyErr_SetObject.restype = None - ############################################################## # ____________________ Built-in functions ____________________ @@ -201,3 +210,27 @@ ##PyCFunction_NewEx = cpyapi.PyCFunction_NewEx ##PyCFunction_NewEx.argtypes = [POINTER(PyMethodDef), W_Object, W_Object] ##PyCFunction_NewEx.restype = W_Object + + +############################################################## +# ____________________ Exception handling ____________________ + +# "RAW" because it comes from pythonapi instead of cpyapi. +# The normal error handling (wrapping CPython exceptions into +# an OperationError) is disabled. +RAW_PyErr_SetObject = pythonapi.PyErr_SetObject +RAW_PyErr_SetObject.argtypes = [W_Object, W_Object] +RAW_PyErr_SetObject.restype = None +RAW_PyErr_SetObject._rctypes_pyerrchecker_ = None + +RAW_PyErr_Occurred = pythonapi.PyErr_Occurred +RAW_PyErr_Occurred.argtypes = [] +RAW_PyErr_Occurred.restype = c_int +RAW_PyErr_Occurred._rctypes_pyerrchecker_ = None + +RAW_PyErr_Fetch = pythonapi.PyErr_Fetch +RAW_PyErr_Fetch.argtypes = [POINTER(W_Object), + POINTER(W_Object), + POINTER(W_Object)] +RAW_PyErr_Fetch.restype = None +RAW_PyErr_Fetch._rctypes_pyerrchecker_ = None Modified: pypy/dist/pypy/objspace/cpy/ctypes_base.py ============================================================================== --- pypy/dist/pypy/objspace/cpy/ctypes_base.py (original) +++ pypy/dist/pypy/objspace/cpy/ctypes_base.py Tue May 2 17:50:12 2006 @@ -26,6 +26,15 @@ class LevelError(Exception): pass +def rctypes_pyerrchecker(): + from pypy.objspace.cpy.capi import RAW_PyErr_Occurred, RAW_PyErr_Fetch + if RAW_PyErr_Occurred(): + w_exc = W_Object() + w_val = W_Object() + w_tb = W_Object() + RAW_PyErr_Fetch(byref(w_exc), byref(w_val), byref(w_tb)) + raise OperationError(w_exc, w_val) # XXX traceback + class CPyAPI(PyDLL): """Class of the singleton 'cpyapi' object, out of which C functions are getattr'd. It returns C function whose exception behavior matches @@ -34,6 +43,7 @@ """ class _FuncPtr(PyDLL._FuncPtr): _flags_ = PyDLL._FuncPtr._flags_ + _rctypes_pyerrchecker_ = staticmethod(rctypes_pyerrchecker) def __call__(*args, **kwds): try: @@ -43,8 +53,7 @@ except: exc, val, tb = sys.exc_info() raise OperationError(W_Object(exc), - W_Object(val), - W_Object(tb)) + W_Object(val)) # XXX traceback cpyapi = CPyAPI.__new__(CPyAPI) cpyapi.__dict__ = pythonapi.__dict__.copy() Modified: pypy/dist/pypy/objspace/cpy/objspace.py ============================================================================== --- pypy/dist/pypy/objspace/cpy/objspace.py (original) +++ pypy/dist/pypy/objspace/cpy/objspace.py Tue May 2 17:50:12 2006 @@ -10,6 +10,7 @@ def initialize(self): self.options.geninterp = True self.w_int = W_Object(int) + self.w_tuple = W_Object(tuple) self.w_None = W_Object(None) self.w_False = W_Object(False) self.w_True = W_Object(True) @@ -66,6 +67,7 @@ int_w = staticmethod(PyInt_AsLong) str_w = staticmethod(PyString_AsString) iter = staticmethod(PyObject_GetIter) + type = staticmethod(PyObject_Type) add = staticmethod(PyNumber_Add) sub = staticmethod(PyNumber_Subtract) @@ -135,3 +137,12 @@ if not w_res: raise OperationError(self.w_StopIteration, self.w_None) return w_res + + def is_true(self, w_obj): + return PyObject_IsTrue(w_obj) != 0 + + def issubtype(self, w_type1, w_type2): + if PyType_IsSubtype(w_type1, w_type2): + return self.w_True + else: + return self.w_False Modified: pypy/dist/pypy/objspace/cpy/test/test_compile.py ============================================================================== --- pypy/dist/pypy/objspace/cpy/test/test_compile.py (original) +++ pypy/dist/pypy/objspace/cpy/test/test_compile.py Tue May 2 17:50:12 2006 @@ -5,6 +5,7 @@ from pypy.objspace.cpy.ann_policy import CPyAnnotatorPolicy from pypy.objspace.cpy.objspace import CPyObjSpace import pypy.rpython.rctypes.implementation +from pypy.interpreter.error import OperationError from pypy.interpreter.function import BuiltinFunction from pypy.interpreter.gateway import interp2app, ObjSpace, W_Root from pypy import conftest @@ -104,3 +105,65 @@ annotatorpolicy = CPyAnnotatorPolicy(space)) res = fn(10, complex) assert isinstance(res, int) + +# ____________________________________________________________ + +def test_compile_exception_to_rpython(): + space = CPyObjSpace() + def entrypoint(n): + w_sys = space.getbuiltinmodule('sys') + w_n = space.wrap(n) + try: + space.call_method(w_sys, 'exit', w_n) + except OperationError, e: + # a bit fragile: this test assumes that the OperationError + # is *not* normalized + return space.newtuple([e.w_type, e.w_value]) + else: + return space.wrap('did not raise??') + + fn = compile(entrypoint, [int], + annotatorpolicy = CPyAnnotatorPolicy(space)) + result = fn(5) + assert result == (SystemExit, 5) + +def test_compile_exception_from_rpython(): + space = CPyObjSpace() + w_SystemExit = space.W_Object(SystemExit) + def myfunc(n): + if n > 0: + raise OperationError(w_SystemExit, space.wrap(n)) + else: + return space.wrap(n) + myfunc.unwrap_spec = [int] + w_myfunc = space.wrap(interp2app(myfunc)) + + def entrypoint(): + return w_myfunc + + fn = compile(entrypoint, [], + annotatorpolicy = CPyAnnotatorPolicy(space)) + myfunc1 = fn() + e = py.test.raises(SystemExit, myfunc1, 5) + ex = e.value + assert ex.args == (5,) + +def test_compile_exception_through_rpython(): + space = CPyObjSpace() + def myfunc(n): + w_sys = space.getbuiltinmodule('sys') + w_n = space.wrap(n) + space.call_method(w_sys, 'exit', w_n) + return space.w_None # should not actually reach this point + myfunc.unwrap_spec = [int] + w_myfunc = space.wrap(interp2app(myfunc)) + + def entrypoint(): + return w_myfunc + + fn = compile(entrypoint, [], + annotatorpolicy = CPyAnnotatorPolicy(space)) + myfunc1 = fn() + e = py.test.raises(SystemExit, myfunc1, 5) + ex = e.value + assert ex.args == (5,) Modified: pypy/dist/pypy/objspace/cpy/wrappable.py ============================================================================== --- pypy/dist/pypy/objspace/cpy/wrappable.py (original) +++ pypy/dist/pypy/objspace/cpy/wrappable.py Tue May 2 17:50:12 2006 @@ -78,9 +78,11 @@ sourcelines.append(' except ___OperationError, e:') sourcelines.append(' ___PyErr_SetObject(e.w_type.value,') sourcelines.append(' e.w_value.value)') - sourcelines.append(' return None') # should never be seen - sourcelines.append(' #except ___Exception, e:') - sourcelines.append(' # raise ___RPythonError(XXX)') + # the following line is not reached, unless we are translated + # in which case it makes the function return (PyObject*)NULL. + sourcelines.append(' w_result = ___W_Object()') + #sourcelines.append(' except ___Exception, e:') + #sourcelines.append(' raise ___RPythonError(XXX)') sourcelines.append(' return w_result.value') sourcelines.append('') Modified: pypy/dist/pypy/rpython/rctypes/afunc.py ============================================================================== --- pypy/dist/pypy/rpython/rctypes/afunc.py (original) +++ pypy/dist/pypy/rpython/rctypes/afunc.py Tue May 2 17:50:12 2006 @@ -114,7 +114,12 @@ kwds = {} if hasattr(cfuncptr, 'llinterp_friendly_version'): kwds['_callable'] = cfuncptr.llinterp_friendly_version + suppress_pyerr_occurred = False if (cfuncptr._flags_ & ctypes._FUNCFLAG_PYTHONAPI) == 0: + suppress_pyerr_occurred = True + if hasattr(cfuncptr, '_rctypes_pyerrchecker_'): + suppress_pyerr_occurred = True + if suppress_pyerr_occurred: kwds['includes'] = getattr(cfuncptr, 'includes', ()) #else: # no 'includes': hack to trigger in GenC a PyErr_Occurred() check @@ -132,6 +137,19 @@ last_op.args[0].value._set_T(FUNCTYPE) last_op.args[0].value._obj._TYPE = FUNCTYPE + if getattr(cfuncptr, '_rctypes_pyerrchecker_', None): + # special extension to support the CPyObjSpace + # XXX hackish: someone else -- like the annotator policy -- + # must ensure that this extra function has been annotated + from pypy.translator.translator import graphof + func = cfuncptr._rctypes_pyerrchecker_ + graph = graphof(hop.rtyper.annotator.translator, func) + hop.llops.record_extra_call(graph) + # build the 'direct_call' operation + f = hop.rtyper.getcallable(graph) + c = hop.inputconst(lltype.typeOf(f), f) + hop.genop('direct_call', [c]) + if RESTYPE is lltype.Void: return None else: Modified: pypy/dist/pypy/rpython/rctypes/test/test_rfunc.py ============================================================================== --- pypy/dist/pypy/rpython/rctypes/test/test_rfunc.py (original) +++ pypy/dist/pypy/rpython/rctypes/test/test_rfunc.py Tue May 2 17:50:12 2006 @@ -323,6 +323,36 @@ assert res == 34 py.test.raises(OverflowError, 'fn(sys.maxint, 1)') + def test_compile_pyerrchecker(self): + from pypy.rpython.rctypes import apyobject + class W_Object(py_object): + pass + apyobject.register_py_object_subclass(W_Object) + + def mypyerrchecker(): + # for this test, always raises + raise ZeroDivisionError + + PyNumber_Add = pythonapi.PyNumber_Add + PyNumber_Add.argtypes = [W_Object, W_Object] + PyNumber_Add.restype = W_Object + assert PyNumber_Add._flags_ & _FUNCFLAG_PYTHONAPI + PyNumber_Add._rctypes_pyerrchecker_ = mypyerrchecker + # special extension ^^^ to support the CPyObjSpace + try: + def fn1(n): + if n < 0: + # for this test, force mypyerrchecker() to be annotated + # using this trick + mypyerrchecker() + pyobj = W_Object(n) + return PyNumber_Add(pyobj, pyobj) + + fn = compile(fn1, [int]) + py.test.raises(ZeroDivisionError, fn, 64) + finally: + del PyNumber_Add._rctypes_pyerrchecker_ + def test_compile_ctime(self): import time N = 123456789 From arigo at codespeak.net Tue May 2 19:11:57 2006 From: arigo at codespeak.net (arigo at codespeak.net) Date: Tue, 2 May 2006 19:11:57 +0200 (CEST) Subject: [pypy-svn] r26680 - in pypy/dist/pypy: annotation rpython/rctypes rpython/rctypes/test translator/backendopt translator/backendopt/test Message-ID: <20060502171157.AA3C0100BE@code0.codespeak.net> Author: arigo Date: Tue May 2 19:11:55 2006 New Revision: 26680 Modified: pypy/dist/pypy/annotation/binaryop.py pypy/dist/pypy/annotation/model.py pypy/dist/pypy/rpython/rctypes/rpyobject.py pypy/dist/pypy/rpython/rctypes/test/test_overhead.py pypy/dist/pypy/rpython/rctypes/test/test_rpyobject.py pypy/dist/pypy/translator/backendopt/malloc.py pypy/dist/pypy/translator/backendopt/test/test_malloc.py Log: (pedronis, arigo) Support for mixing None and py_object() -- not other ctypes objects, only py_object, because the rules for what 'None' means when in ctypes are, let's say, interesting. Modified: pypy/dist/pypy/annotation/binaryop.py ============================================================================== --- pypy/dist/pypy/annotation/binaryop.py (original) +++ pypy/dist/pypy/annotation/binaryop.py Tue May 2 19:11:55 2006 @@ -810,3 +810,17 @@ return SomeCTypesObject(s_cto1.knowntype, state) else: return SomeObject() + +class __extend__(pairtype(SomeCTypesObject, SomePBC)): + def union((obj, pbc)): + if pbc.isNone() and obj.can_be_none(): + return obj + else: + return SomeObject() + +class __extend__(pairtype(SomePBC, SomeCTypesObject)): + def union((pbc, obj)): + if pbc.isNone() and obj.can_be_none(): + return obj + else: + return SomeObject() Modified: pypy/dist/pypy/annotation/model.py ============================================================================== --- pypy/dist/pypy/annotation/model.py (original) +++ pypy/dist/pypy/annotation/model.py Tue May 2 19:11:55 2006 @@ -427,7 +427,9 @@ self.memorystate = memorystate def can_be_none(self): - return False + # only 'py_object' can also be None + import ctypes + return issubclass(self.knowntype, ctypes.py_object) def return_annotation(self): """Returns either 'self' or the annotation of the unwrapped version Modified: pypy/dist/pypy/rpython/rctypes/rpyobject.py ============================================================================== --- pypy/dist/pypy/rpython/rctypes/rpyobject.py (original) +++ pypy/dist/pypy/rpython/rctypes/rpyobject.py Tue May 2 19:11:55 2006 @@ -7,6 +7,12 @@ class CTypesPyObjRepr(CTypesValueRepr): + def convert_const(self, value): + if value is None: + return lltype.nullptr(self.lowleveltype.TO) + else: + return super(CTypesPyObjRepr, self).convert_const(value) + def initialize_const(self, p, value): if isinstance(value, self.ctype): value = value.value @@ -29,6 +35,13 @@ pyobj_repr) self.setvalue(hop.llops, v_pyobj, v_newvalue) + def rtype_is_true(self, hop): + [v_box] = hop.inputargs(self) + return hop.gendirectcall(ll_pyobjbox_is_true, v_box) + +def ll_pyobjbox_is_true(box): + return bool(box) and bool(box.c_data[0]) + class __extend__(pairtype(CTypesPyObjRepr, PyObjRepr)): # conversion used by wrapper.py in genc when returning a py_object Modified: pypy/dist/pypy/rpython/rctypes/test/test_overhead.py ============================================================================== --- pypy/dist/pypy/rpython/rctypes/test/test_overhead.py (original) +++ pypy/dist/pypy/rpython/rctypes/test/test_overhead.py Tue May 2 19:11:55 2006 @@ -9,7 +9,7 @@ from pypy.rpython.test.test_llinterp import gengraph from pypy.translator.backendopt.all import backend_optimizations -from ctypes import c_int, Structure, pointer, POINTER +from ctypes import c_int, Structure, pointer, POINTER, py_object def find_mallocs(func, argtypes): @@ -92,3 +92,16 @@ mallocs = find_mallocs(func, []) assert not mallocs # depends on inlining + +def test_using_pyobject(): + def g(n): + if n == 2: + w = py_object() + else: + w = py_object(n) + return w + def func(n): + return bool(g(n)) + + mallocs = find_mallocs(func, [int]) + assert not mallocs # depends on inlining Modified: pypy/dist/pypy/rpython/rctypes/test/test_rpyobject.py ============================================================================== --- pypy/dist/pypy/rpython/rctypes/test/test_rpyobject.py (original) +++ pypy/dist/pypy/rpython/rctypes/test/test_rpyobject.py Tue May 2 19:11:55 2006 @@ -13,7 +13,7 @@ from pypy.rpython.test.test_llinterp import interpret from pypy.rpython.lltypesystem import lltype -from ctypes import py_object +from ctypes import py_object, CFUNCTYPE, c_int class Test_annotation: @@ -46,6 +46,23 @@ if conftest.option.view: a.translator.view() + def test_annotate_mix_with_None(self): + def fn(i): + if i == 1: + p = py_object(123) + elif i == 2: + p = py_object() + else: + p = None + return p + + a = RPythonAnnotator() + s = a.build_types(fn, [int]) + assert s.knowntype == py_object + assert s.can_be_none() # NB. it's actually always True for now + if conftest.option.view: + a.translator.view() + class Test_specialization: def test_specialize_wrapping(self): def wrap(x): @@ -75,3 +92,23 @@ assert res.c_data[0]._obj.value == 5 res = interpret(fn, [1]) assert res.c_data[0]._obj.value == "hello" + + def test_specialize_with_none(self): + def g(i): + if i == 1: + p = py_object(123) + elif i == 2: + p = py_object() + else: + p = None + return p + def fn(i): + p = g(i) + return bool(p), p is None + + res = interpret(fn, [1]) + assert (res.item0, res.item1) == (True, False) + res = interpret(fn, [2]) + assert (res.item0, res.item1) == (False, False) + res = interpret(fn, [3]) + assert (res.item0, res.item1) == (False, True) Modified: pypy/dist/pypy/translator/backendopt/malloc.py ============================================================================== --- pypy/dist/pypy/translator/backendopt/malloc.py (original) +++ pypy/dist/pypy/translator/backendopt/malloc.py Tue May 2 19:11:55 2006 @@ -136,11 +136,13 @@ assert isinstance(STRUCT, lltype.GcStruct) # must be only ever accessed via getfield/setfield/getsubstruct/ - # direct_fieldptr, or touched by keepalive. Note that same_as and - # cast_pointer are not recorded in usepoints. + # direct_fieldptr, or touched by keepalive or ptr_iszero/ptr_nonzero. + # Note that same_as and cast_pointer are not recorded in usepoints. FIELD_ACCESS = dict.fromkeys(["getfield", "setfield", "keepalive", + "ptr_iszero", + "ptr_nonzero", "getarrayitem", "setarrayitem"]) SUBSTRUCT_ACCESS = dict.fromkeys(["getsubstruct", @@ -327,6 +329,12 @@ [v, cname], op.result) newops.append(newop) + elif op.opname in ("ptr_iszero", "ptr_nonzero"): + # we know the pointer is not NULL if it comes from + # a successful malloc + c = Constant(op.opname == "ptr_nonzero", lltype.Bool) + newop = SpaceOperation('same_as', [c], op.result) + newops.append(newop) else: raise AssertionError, op.opname elif op.result in vars: Modified: pypy/dist/pypy/translator/backendopt/test/test_malloc.py ============================================================================== --- pypy/dist/pypy/translator/backendopt/test/test_malloc.py (original) +++ pypy/dist/pypy/translator/backendopt/test/test_malloc.py Tue May 2 19:11:55 2006 @@ -252,3 +252,11 @@ s.a[index].n = 12 return s.a[index].n check(fn, [], [], 12) + +def test_ptr_nonzero(): + from pypy.rpython.lltypesystem import lltype + S = lltype.GcStruct('S') + def fn(): + s = lltype.malloc(S) + return bool(s) + check(fn, [], [], True) From arigo at codespeak.net Tue May 2 20:17:36 2006 From: arigo at codespeak.net (arigo at codespeak.net) Date: Tue, 2 May 2006 20:17:36 +0200 (CEST) Subject: [pypy-svn] r26681 - in pypy/dist/pypy/objspace/cpy: . test Message-ID: <20060502181736.5917E100B7@code0.codespeak.net> Author: arigo Date: Tue May 2 20:17:33 2006 New Revision: 26681 Added: pypy/dist/pypy/objspace/cpy/refcount.py (contents, props changed) pypy/dist/pypy/objspace/cpy/test/test_refcount.py (contents, props changed) Modified: pypy/dist/pypy/objspace/cpy/ann_policy.py pypy/dist/pypy/objspace/cpy/capi.py pypy/dist/pypy/objspace/cpy/ctypes_base.py pypy/dist/pypy/objspace/cpy/test/test_compile.py pypy/dist/pypy/objspace/cpy/wrappable.py Log: (pedronis, arigo) Preserve tracebacks through the RPython code. Added necessary support to manipulate the refcounts directly. Modified: pypy/dist/pypy/objspace/cpy/ann_policy.py ============================================================================== --- pypy/dist/pypy/objspace/cpy/ann_policy.py (original) +++ pypy/dist/pypy/objspace/cpy/ann_policy.py Tue May 2 20:17:33 2006 @@ -29,11 +29,11 @@ # restart this loop: for all we know follow_annotations() # could have found new objects - # force w_type, w_value attributes into the OperationError class + # force w_type/w_value/w_traceback attrs into the OperationError class bk = annotator.bookkeeper classdef = bk.getuniqueclassdef(OperationError) s_instance = annmodel.SomeInstance(classdef=classdef) - for name in ['w_type', 'w_value']: + for name in ['w_type', 'w_value', 'w_traceback']: s_instance.setattr(bk.immutablevalue(name), bk.valueoftype(W_Object)) Modified: pypy/dist/pypy/objspace/cpy/capi.py ============================================================================== --- pypy/dist/pypy/objspace/cpy/capi.py (original) +++ pypy/dist/pypy/objspace/cpy/capi.py Tue May 2 20:17:33 2006 @@ -223,6 +223,12 @@ RAW_PyErr_SetObject.restype = None RAW_PyErr_SetObject._rctypes_pyerrchecker_ = None +# WARNING: consumes references +RAW_PyErr_Restore = pythonapi.PyErr_Restore +RAW_PyErr_Restore.argtypes = [W_Object, W_Object, W_Object] +RAW_PyErr_Restore.restype = None +RAW_PyErr_Restore._rctypes_pyerrchecker_ = None + RAW_PyErr_Occurred = pythonapi.PyErr_Occurred RAW_PyErr_Occurred.argtypes = [] RAW_PyErr_Occurred.restype = c_int Modified: pypy/dist/pypy/objspace/cpy/ctypes_base.py ============================================================================== --- pypy/dist/pypy/objspace/cpy/ctypes_base.py (original) +++ pypy/dist/pypy/objspace/cpy/ctypes_base.py Tue May 2 20:17:33 2006 @@ -33,7 +33,7 @@ w_val = W_Object() w_tb = W_Object() RAW_PyErr_Fetch(byref(w_exc), byref(w_val), byref(w_tb)) - raise OperationError(w_exc, w_val) # XXX traceback + raise OperationError(w_exc, w_val, w_tb) class CPyAPI(PyDLL): """Class of the singleton 'cpyapi' object, out of which C functions @@ -53,7 +53,8 @@ except: exc, val, tb = sys.exc_info() raise OperationError(W_Object(exc), - W_Object(val)) # XXX traceback + W_Object(val), + W_Object(tb)) cpyapi = CPyAPI.__new__(CPyAPI) cpyapi.__dict__ = pythonapi.__dict__.copy() Added: pypy/dist/pypy/objspace/cpy/refcount.py ============================================================================== --- (empty file) +++ pypy/dist/pypy/objspace/cpy/refcount.py Tue May 2 20:17:33 2006 @@ -0,0 +1,69 @@ +from pypy.annotation import model as annmodel +from pypy.rpython.extregistry import ExtRegistryEntry +from pypy.objspace.cpy.capi import * + + +################################################################### +# ____________________ Reference counter hacks ____________________ + +_XX_PyObject_GetItem = pythonapi.PyObject_GetItem +_XX_PyObject_GetItem.argtypes = [W_Object, W_Object] +_XX_PyObject_GetItem.restype = None # ! + +_XX_PyList_SetItem = pythonapi.PyList_SetItem +_XX_PyList_SetItem.argtypes = [W_Object, Py_ssize_t, W_Object] +_XX_PyList_SetItem.restype = c_int + +def Py_Incref(w): + container = (w.value,) + _XX_PyObject_GetItem(W_Object(container), W_Object(0)) + # the new reference returned by PyObject_GetItem is ignored and lost + +def Py_Decref(w): + lst = [None] + # consume a reference + _XX_PyList_SetItem(W_Object(lst), 0, w) + +def Py_XIncref(w): + if w: + Py_Incref(w) + +def Py_XDecref(w): + if w: + Py_Decref(w) + + +class IncrefFnEntry(ExtRegistryEntry): + "Annotation and specialization of calls to Py_Incref()." + _about_ = Py_Incref + + def compute_result_annotation(self, s_arg): + return annmodel.s_None + + def specialize_call(self, hop): + from pypy.rpython.lltypesystem import lltype + s_pyobj = annmodel.SomeCTypesObject(W_Object, + annmodel.SomeCTypesObject.MEMORYALIAS) + r_pyobj = hop.rtyper.getrepr(s_pyobj) + [v_box] = hop.inputargs(r_pyobj) + v_value = r_pyobj.getvalue(hop.llops, v_box) + hop.genop('gc_push_alive_pyobj', [v_value]) + return hop.inputconst(lltype.Void, None) + + +class DecrefFnEntry(ExtRegistryEntry): + "Annotation and specialization of calls to Py_Decref()." + _about_ = Py_Decref + + def compute_result_annotation(self, s_arg): + return annmodel.s_None + + def specialize_call(self, hop): + from pypy.rpython.lltypesystem import lltype + s_pyobj = annmodel.SomeCTypesObject(W_Object, + annmodel.SomeCTypesObject.MEMORYALIAS) + r_pyobj = hop.rtyper.getrepr(s_pyobj) + [v_box] = hop.inputargs(r_pyobj) + v_value = r_pyobj.getvalue(hop.llops, v_box) + hop.genop('gc_pop_alive_pyobj', [v_value]) + return hop.inputconst(lltype.Void, None) Modified: pypy/dist/pypy/objspace/cpy/test/test_compile.py ============================================================================== --- pypy/dist/pypy/objspace/cpy/test/test_compile.py (original) +++ pypy/dist/pypy/objspace/cpy/test/test_compile.py Tue May 2 20:17:33 2006 @@ -150,12 +150,10 @@ def test_compile_exception_through_rpython(): space = CPyObjSpace() - def myfunc(n): - w_sys = space.getbuiltinmodule('sys') - w_n = space.wrap(n) - space.call_method(w_sys, 'exit', w_n) + def myfunc(w_callback): + space.call_function(w_callback, space.wrap(5)) return space.w_None # should not actually reach this point - myfunc.unwrap_spec = [int] + myfunc.unwrap_spec = [W_Root] w_myfunc = space.wrap(interp2app(myfunc)) def entrypoint(): @@ -163,7 +161,13 @@ fn = compile(entrypoint, [], annotatorpolicy = CPyAnnotatorPolicy(space)) + + def mycallback(n): + assert n == 5 + raise SystemExit(12) + myfunc1 = fn() - e = py.test.raises(SystemExit, myfunc1, 5) + e = py.test.raises(SystemExit, myfunc1, mycallback) ex = e.value - assert ex.args == (5,) + assert ex.args == (12,) + assert e.traceback[-1].frame.code.name == 'mycallback' Added: pypy/dist/pypy/objspace/cpy/test/test_refcount.py ============================================================================== --- (empty file) +++ pypy/dist/pypy/objspace/cpy/test/test_refcount.py Tue May 2 20:17:33 2006 @@ -0,0 +1,39 @@ +import sys +from pypy.translator.c.test.test_genc import compile +from pypy.objspace.cpy.refcount import * + + +def test_reftricks(): + x = object() + w_x = W_Object(x) + before = sys.getrefcount(x) + Py_Incref(w_x) + after = sys.getrefcount(x) + assert after == before+1 + assert w_x.value is x + + Py_Decref(w_x) + after = sys.getrefcount(x) + assert after == before + assert w_x.value is x + + +def test_compile_reftricks(): + def func(obj, flag): + w = W_Object(obj) + if flag > 0: + Py_Incref(w) + else: + Py_Decref(w) + + fn = compile(func, [object, int]) + + x = object() + before = sys.getrefcount(x) + fn(x, +1) + after = sys.getrefcount(x) + assert after == before+1 + + fn(x, -1) + after = sys.getrefcount(x) + assert after == before Modified: pypy/dist/pypy/objspace/cpy/wrappable.py ============================================================================== --- pypy/dist/pypy/objspace/cpy/wrappable.py (original) +++ pypy/dist/pypy/objspace/cpy/wrappable.py Tue May 2 20:17:33 2006 @@ -6,6 +6,7 @@ import py from pypy.annotation.pairtype import pair, pairtype from pypy.objspace.cpy.capi import * +from pypy.objspace.cpy.refcount import Py_XIncref from pypy.objspace.cpy.objspace import CPyObjSpace from pypy.interpreter.error import OperationError from pypy.interpreter.function import Function @@ -49,6 +50,19 @@ self.passedargs = [] +def reraise(e): + w_type = e.w_type + w_value = e.w_value + w_traceback = e.application_traceback + if e.application_traceback is None: + w_traceback = W_Object() # NULL + else: + Py_XIncref(w_traceback) + Py_XIncref(w_type) + Py_XIncref(w_value) + RAW_PyErr_Restore(e.w_type, e.w_value, w_traceback) + + class __extend__(pairtype(CPyObjSpace, Function)): def wrap((space, func)): @@ -76,8 +90,7 @@ sourcelines.append(' w_result = ___bltin(%s)' % ( ', '.join(tramp.passedargs),)) sourcelines.append(' except ___OperationError, e:') - sourcelines.append(' ___PyErr_SetObject(e.w_type.value,') - sourcelines.append(' e.w_value.value)') + sourcelines.append(' ___reraise(e)') # the following line is not reached, unless we are translated # in which case it makes the function return (PyObject*)NULL. sourcelines.append(' w_result = ___W_Object()') @@ -92,7 +105,7 @@ '___PyInt_AsLong': PyInt_AsLong, '___bltin': bltin, '___OperationError': OperationError, - '___PyErr_SetObject': RAW_PyErr_SetObject, + '___reraise': reraise, } exec py.code.Source('\n'.join(sourcelines)).compile() in miniglobals From arigo at codespeak.net Tue May 2 20:36:28 2006 From: arigo at codespeak.net (arigo at codespeak.net) Date: Tue, 2 May 2006 20:36:28 +0200 (CEST) Subject: [pypy-svn] r26683 - pypy/dist/pypy/objspace/cpy Message-ID: <20060502183628.9FD5F100BB@code0.codespeak.net> Author: arigo Date: Tue May 2 20:36:27 2006 New Revision: 26683 Modified: pypy/dist/pypy/objspace/cpy/capi.py pypy/dist/pypy/objspace/cpy/objspace.py Log: (pedronis, arigo) Optimized space.newlist() with the help of Py_Incref(). Modified: pypy/dist/pypy/objspace/cpy/capi.py ============================================================================== --- pypy/dist/pypy/objspace/cpy/capi.py (original) +++ pypy/dist/pypy/objspace/cpy/capi.py Tue May 2 20:36:27 2006 @@ -162,6 +162,10 @@ PyTuple_New.argtypes = [Py_ssize_t] PyTuple_New.restype = W_Object +PyTuple_SetItem = cpyapi.PyTuple_SetItem +PyTuple_SetItem.argtypes = [W_Object, Py_ssize_t, W_Object] +PyTuple_SetItem.restype = c_int + ################################################# # ____________________ Lists ____________________ @@ -174,6 +178,10 @@ PyList_Append.argtypes = [W_Object, W_Object] PyList_Append.restype = c_int +PyList_SetItem = cpyapi.PyList_SetItem +PyList_SetItem.argtypes = [W_Object, Py_ssize_t, W_Object] +PyList_SetItem.restype = c_int + ######################################################## # ____________________ Dictionaries ____________________ @@ -194,6 +202,10 @@ PyImport_ImportModule.argtypes = [c_char_p] PyImport_ImportModule.restype = W_Object +_PyObject_Dump = cpyapi._PyObject_Dump +_PyObject_Dump.argtypes = [W_Object] +_PyObject_Dump.restype = None + ############################################################## # ____________________ Built-in functions ____________________ Modified: pypy/dist/pypy/objspace/cpy/objspace.py ============================================================================== --- pypy/dist/pypy/objspace/cpy/objspace.py (original) +++ pypy/dist/pypy/objspace/cpy/objspace.py Tue May 2 20:36:27 2006 @@ -1,4 +1,5 @@ from pypy.objspace.cpy.capi import * +from pypy.objspace.cpy.refcount import Py_Incref from pypy.annotation.pairtype import pair from pypy.interpreter import baseobjspace from pypy.interpreter.error import OperationError @@ -98,16 +99,17 @@ return w_dict def newlist(self, items_w): - w_list = PyList_New(0) - for w_item in items_w: - # XXX inefficient but: - # PyList_SetItem steals a ref so it's harder to use - # PySequence_SetItem crashes if it replaces a NULL item - PyList_Append(w_list, w_item) + n = len(items_w) + w_list = PyList_New(n) + for i in range(n): + w_item = items_w[i] + Py_Incref(w_item) + PyList_SetItem(w_list, i, w_item) return w_list def newtuple(self, items_w): - # XXX not very efficient, but PyTuple_SetItem steals a ref + # XXX not very efficient, but PyTuple_SetItem complains if the + # refcount of the tuple is not exactly 1 w_list = self.newlist(items_w) return PySequence_Tuple(w_list) From dialtone at codespeak.net Tue May 2 21:09:09 2006 From: dialtone at codespeak.net (dialtone at codespeak.net) Date: Tue, 2 May 2006 21:09:09 +0200 (CEST) Subject: [pypy-svn] r26684 - pypy/dist/pypy/translator/cl/test Message-ID: <20060502190909.2522B100AC@code0.codespeak.net> Author: dialtone Date: Tue May 2 21:09:08 2006 New Revision: 26684 Modified: pypy/dist/pypy/translator/cl/test/test_cltrans.py Log: unskip a test that passes and use more informative skip messages for the others Modified: pypy/dist/pypy/translator/cl/test/test_cltrans.py ============================================================================== --- pypy/dist/pypy/translator/cl/test/test_cltrans.py (original) +++ pypy/dist/pypy/translator/cl/test/test_cltrans.py Tue May 2 21:09:08 2006 @@ -114,7 +114,7 @@ assert f6(30) == 3657 def test_string(): - py.test.skip("temporarily disabled") + py.test.skip("strings not supported") cl_greet = make_cl_func(t.greet, [str]) assert cl_greet("world") == "helloworld" cl_stringmaker = make_cl_func(t.nested_whiles, [int, int]) @@ -122,29 +122,28 @@ "...!...!...!...!...!") def test_for(): - py.test.skip("temporarily disabled") + py.test.skip("strings not supported") cl_python = make_cl_func(t.choose_last) assert cl_python() == "python" def test_builtin(): - py.test.skip("temporarily disabled") cl_builtinusage = make_cl_func(t.builtinusage) assert cl_builtinusage() == 4 def test_slice(): - py.test.skip("temporarily disabled") + py.test.skip("either this is not RPython or gencl has something horribly wrong") cl_half = make_cl_func(t.half_of_n, [int]) assert cl_half(10) == 5 def test_powerset(): - py.test.skip("temporarily disabled") + py.test.skip("another test that fails in the rtyper, not RPython?") cl_powerset = make_cl_func(t.powerset, [int]) result = cl_powerset(3) assert result.__class__ == Literal assert result.val == ( '#(#() #(0) #(1) #(0 1) #(2) #(0 2) #(1 2) #(0 1 2))') def test_yast(): - py.test.skip("temporarily disabled") + py.test.skip("missing op_iter") cl_sum = make_cl_func(t.yast, [list]) # yet another sum test assert cl_sum(range(12)) == 66 From arigo at codespeak.net Tue May 2 21:34:11 2006 From: arigo at codespeak.net (arigo at codespeak.net) Date: Tue, 2 May 2006 21:34:11 +0200 (CEST) Subject: [pypy-svn] r26685 - in pypy/dist/pypy: interpreter objspace/cpy rpython rpython/lltypesystem translator translator/c translator/goal Message-ID: <20060502193411.E9C79100AC@code0.codespeak.net> Author: arigo Date: Tue May 2 21:34:04 2006 New Revision: 26685 Modified: pypy/dist/pypy/interpreter/baseobjspace.py pypy/dist/pypy/interpreter/gateway.py pypy/dist/pypy/objspace/cpy/objspace.py pypy/dist/pypy/rpython/lltypesystem/rclass.py pypy/dist/pypy/rpython/rtyper.py pypy/dist/pypy/translator/c/genc.py pypy/dist/pypy/translator/c/pyobj.py pypy/dist/pypy/translator/driver.py pypy/dist/pypy/translator/goal/targetdemomodule.py Log: (pedronis, arigo) Change one line here and one line there until we can translate the _demo module more or less completely, with only lots of small details left to fix! Modified: pypy/dist/pypy/interpreter/baseobjspace.py ============================================================================== --- pypy/dist/pypy/interpreter/baseobjspace.py (original) +++ pypy/dist/pypy/interpreter/baseobjspace.py Tue May 2 21:34:04 2006 @@ -632,14 +632,15 @@ raise TypeError, 'space.eval(): expected a string, code or PyCode object' return expression.exec_code(self, w_globals, w_locals) - def exec_(self, statement, w_globals, w_locals): + def exec_(self, statement, w_globals, w_locals, hidden_applevel=False): "NOT_RPYTHON: For internal debugging." import types from pypy.interpreter.pycode import PyCode if isinstance(statement, str): statement = compile(statement, '?', 'exec') if isinstance(statement, types.CodeType): - statement = PyCode._from_code(self, statement) + statement = PyCode._from_code(self, statement, + hidden_applevel=hidden_applevel) if not isinstance(statement, PyCode): raise TypeError, 'space.exec_(): expected a string, code or PyCode object' w_key = self.wrap('__builtins__') Modified: pypy/dist/pypy/interpreter/gateway.py ============================================================================== --- pypy/dist/pypy/interpreter/gateway.py (original) +++ pypy/dist/pypy/interpreter/gateway.py Tue May 2 21:34:04 2006 @@ -817,10 +817,10 @@ def build_applevel_dict(self, space): "NOT_RPYTHON" from pypy.interpreter.pycode import PyCode - pycode = PyCode._from_code(space, self.code, hidden_applevel=self.hidden_applevel) w_glob = space.newdict([]) space.setitem(w_glob, space.wrap('__name__'), space.wrap('__builtin__')) - space.exec_(pycode, w_glob, w_glob) + space.exec_(self.code, w_glob, w_glob, + hidden_applevel=self.hidden_applevel) return w_glob # __________ geninterplevel version __________ Modified: pypy/dist/pypy/objspace/cpy/objspace.py ============================================================================== --- pypy/dist/pypy/objspace/cpy/objspace.py (original) +++ pypy/dist/pypy/objspace/cpy/objspace.py Tue May 2 21:34:04 2006 @@ -9,7 +9,7 @@ from pypy.objspace.cpy.ctypes_base import W_Object def initialize(self): - self.options.geninterp = True + self.options.geninterp = False self.w_int = W_Object(int) self.w_tuple = W_Object(tuple) self.w_None = W_Object(None) @@ -148,3 +148,10 @@ return self.w_True else: return self.w_False + + def exec_(self, statement, w_globals, w_locals, hidden_applevel=False): + "NOT_RPYTHON" + from types import CodeType + if not isinstance(statement, (str, CodeType)): + raise TypeError("CPyObjSpace.exec_(): only for CPython code objs") + exec statement in w_globals.value, w_locals.value Modified: pypy/dist/pypy/rpython/lltypesystem/rclass.py ============================================================================== --- pypy/dist/pypy/rpython/lltypesystem/rclass.py (original) +++ pypy/dist/pypy/rpython/lltypesystem/rclass.py Tue May 2 21:34:04 2006 @@ -388,7 +388,8 @@ return malloc(self.object_type, flavor=self.getflavor()) # pick flavor def has_wrapper(self): - return self.rtyper.needs_wrapper(self.classdef) + return self.classdef is not None and ( + self.rtyper.needs_wrapper(self.classdef.classdesc.pyobj)) has_wrapper = property(has_wrapper) def get_ll_hash_function(self): Modified: pypy/dist/pypy/rpython/rtyper.py ============================================================================== --- pypy/dist/pypy/rpython/rtyper.py (original) +++ pypy/dist/pypy/rpython/rtyper.py Tue May 2 21:34:04 2006 @@ -56,7 +56,7 @@ self.class_reprs = {} self.instance_reprs = {} self.pbc_reprs = {} - self.classdefs_with_wrapper = {} + self.classes_with_wrapper = {} self.wrapper_context = None # or add an extra arg to convertvar? self.concrete_calltables = {} self.class_pbc_attributes = {} @@ -91,8 +91,9 @@ def add_wrapper(self, clsdef): # record that this class has a wrapper, and what the __init__ is - init = getattr(clsdef.classdesc.pyobj.__init__, 'im_func', None) - self.classdefs_with_wrapper[clsdef] = init + cls = clsdef.classdesc.pyobj + init = getattr(cls.__init__, 'im_func', None) + self.classes_with_wrapper[cls] = init def set_wrapper_context(self, obj): # not nice, but we sometimes need to know which function we are wrapping @@ -549,11 +550,12 @@ def needs_hash_support(self, clsdef): return clsdef in self.annotator.bookkeeper.needs_hash_support - def needs_wrapper(self, clsdef): - return clsdef in self.classdefs_with_wrapper + def needs_wrapper(self, cls): + return cls in self.classes_with_wrapper def get_wrapping_hint(self, clsdef): - return self.classdefs_with_wrapper[clsdef], self.wrapper_context + cls = clsdef.classdesc.pyobj + return self.classes_with_wrapper[cls], self.wrapper_context def getcallable(self, graph): def getconcretetype(v): Modified: pypy/dist/pypy/translator/c/genc.py ============================================================================== --- pypy/dist/pypy/translator/c/genc.py (original) +++ pypy/dist/pypy/translator/c/genc.py Tue May 2 21:34:04 2006 @@ -21,6 +21,7 @@ symboltable = None stackless = False use_stackless_transformation = False + modulename = None def __init__(self, translator, entrypoint, gcpolicy=None, libraries=None, thread_enabled=False): self.translator = translator @@ -87,7 +88,9 @@ pf = self.getentrypointptr() pfname = db.get(pf) - modulename = uniquemodulename('testing') + if self.modulename is None: + self.modulename = uniquemodulename('testing') + modulename = self.modulename targetdir = udir.ensure(modulename, dir=1) self.targetdir = targetdir defines = {} Modified: pypy/dist/pypy/translator/c/pyobj.py ============================================================================== --- pypy/dist/pypy/translator/c/pyobj.py (original) +++ pypy/dist/pypy/translator/c/pyobj.py Tue May 2 21:34:04 2006 @@ -344,10 +344,8 @@ return name def nameof_classobj(self, cls): - if isinstance(cls, ClassType) or builtin_type_base(cls) is object: - clsdef = self.translator.annotator.bookkeeper.getuniqueclassdef(cls) - if self.translator.rtyper.needs_wrapper(clsdef): - return self.wrap_exported_class(cls) + if self.translator.rtyper.needs_wrapper(cls): + return self.wrap_exported_class(cls) if cls.__doc__ and cls.__doc__.lstrip().startswith('NOT_RPYTHON'): raise Exception, "%r should never be reached" % (cls,) Modified: pypy/dist/pypy/translator/driver.py ============================================================================== --- pypy/dist/pypy/translator/driver.py (original) +++ pypy/dist/pypy/translator/driver.py Tue May 2 21:34:04 2006 @@ -245,6 +245,8 @@ gcpolicy = gcpolicy, thread_enabled = getattr(opt, 'thread', False)) cbuilder.stackless = opt.stackless + if not standalone: # xxx messy + cbuilder.modulename = self.exe_name % self.options.__dict__ database = cbuilder.build_database() self.log.info("database for generating C source was created") self.cbuilder = cbuilder Modified: pypy/dist/pypy/translator/goal/targetdemomodule.py ============================================================================== --- pypy/dist/pypy/translator/goal/targetdemomodule.py (original) +++ pypy/dist/pypy/translator/goal/targetdemomodule.py Tue May 2 21:34:04 2006 @@ -5,7 +5,6 @@ space = CPyObjSpace() -Module.appleveldefs.clear() # XXX! for now module = Module(space, space.wrap('_demo')) w_moduledict = module.getdict() @@ -17,7 +16,8 @@ # _____ Define and setup target ___ -def target(*args): +def target(driver, args): + driver.exe_name = '_demo' return __init__, [object], CPyAnnotatorPolicy(space) From pedronis at codespeak.net Tue May 2 22:42:31 2006 From: pedronis at codespeak.net (pedronis at codespeak.net) Date: Tue, 2 May 2006 22:42:31 +0200 (CEST) Subject: [pypy-svn] r26686 - pypy/dist/pypy/rpython Message-ID: <20060502204231.A3E271008A@code0.codespeak.net> Author: pedronis Date: Tue May 2 22:42:30 2006 New Revision: 26686 Modified: pypy/dist/pypy/rpython/rtyper.py Log: avoids the cost of constructing fresh SomeObjects each time. Modified: pypy/dist/pypy/rpython/rtyper.py ============================================================================== --- pypy/dist/pypy/rpython/rtyper.py (original) +++ pypy/dist/pypy/rpython/rtyper.py Tue May 2 22:42:30 2006 @@ -137,8 +137,8 @@ self.add_pendingsetup(result) return result - def binding(self, var): - s_obj = self.annotator.binding(var, annmodel.SomeObject()) + def binding(self, var, default=annmodel.SomeObject()): + s_obj = self.annotator.binding(var, default) return s_obj def bindingrepr(self, var): From dialtone at codespeak.net Tue May 2 23:15:02 2006 From: dialtone at codespeak.net (dialtone at codespeak.net) Date: Tue, 2 May 2006 23:15:02 +0200 (CEST) Subject: [pypy-svn] r26687 - pypy/dist/pypy/translator/cl/test Message-ID: <20060502211502.7C4A110080@code0.codespeak.net> Author: dialtone Date: Tue May 2 23:15:01 2006 New Revision: 26687 Modified: pypy/dist/pypy/translator/cl/test/test_cltrans.py Log: passing a modified yast without modifications, introducing a copy of yast to fix name clashes problems Modified: pypy/dist/pypy/translator/cl/test/test_cltrans.py ============================================================================== --- pypy/dist/pypy/translator/cl/test/test_cltrans.py (original) +++ pypy/dist/pypy/translator/cl/test/test_cltrans.py Tue May 2 23:15:01 2006 @@ -143,9 +143,18 @@ assert result.val == ( '#(#() #(0) #(1) #(0 1) #(2) #(0 2) #(1 2) #(0 1 2))') def test_yast(): - py.test.skip("missing op_iter") - cl_sum = make_cl_func(t.yast, [list]) # yet another sum test - assert cl_sum(range(12)) == 66 + def yast1(n): + # Need this to avoid name clashes in the generated code + return t.yast(range(n)) + cl_sum = make_cl_func(yast1, [int]) # yet another sum test + assert cl_sum(12) == 66 + +def test_name_clash(): + py.test.skip("Name clash between the 2 yast functions") + def yast(n): + return t.yast(range(n)) + cl_sum = make_cl_func(yast, [int]) + assert cl_sum(12) == 66 def test_int_add(): def add_two(number): @@ -159,5 +168,3 @@ # - append/reverse. not RPython. delegate? # attrs # - attribute. need object. symbol-plist? -# yast -# - need way to specify that argument is list of int. From arigo at codespeak.net Wed May 3 10:07:34 2006 From: arigo at codespeak.net (arigo at codespeak.net) Date: Wed, 3 May 2006 10:07:34 +0200 (CEST) Subject: [pypy-svn] r26709 - in pypy/dist/pypy/translator: . goal Message-ID: <20060503080734.49246100C6@code0.codespeak.net> Author: arigo Date: Wed May 3 10:07:33 2006 New Revision: 26709 Modified: pypy/dist/pypy/translator/driver.py pypy/dist/pypy/translator/goal/targetdemomodule.py Log: Oups! The default name 'target-c' is not good for extension modules, with the '-'. Modified: pypy/dist/pypy/translator/driver.py ============================================================================== --- pypy/dist/pypy/translator/driver.py (original) +++ pypy/dist/pypy/translator/driver.py Wed May 3 10:07:33 2006 @@ -42,7 +42,7 @@ class TranslationDriver(SimpleTaskEngine): def __init__(self, options=None, default_goal=None, disable=[], - exe_name = 'target-%(backend)s'): + exe_name = 'target-%(backend)s', extmod_name=None): SimpleTaskEngine.__init__(self) self.log = log @@ -51,6 +51,7 @@ options = DEFAULT_OPTIONS self.options = options self.exe_name = exe_name + self.extmod_name = extmod_name self.done = {} @@ -245,8 +246,8 @@ gcpolicy = gcpolicy, thread_enabled = getattr(opt, 'thread', False)) cbuilder.stackless = opt.stackless - if not standalone: # xxx messy - cbuilder.modulename = self.exe_name % self.options.__dict__ + if not standalone: # xxx more messy + cbuilder.modulename = self.extmod_name database = cbuilder.build_database() self.log.info("database for generating C source was created") self.cbuilder = cbuilder Modified: pypy/dist/pypy/translator/goal/targetdemomodule.py ============================================================================== --- pypy/dist/pypy/translator/goal/targetdemomodule.py (original) +++ pypy/dist/pypy/translator/goal/targetdemomodule.py Wed May 3 10:07:33 2006 @@ -17,7 +17,7 @@ # _____ Define and setup target ___ def target(driver, args): - driver.exe_name = '_demo' + driver.extmod_name = '_demo' return __init__, [object], CPyAnnotatorPolicy(space) From bea at codespeak.net Wed May 3 10:41:31 2006 From: bea at codespeak.net (bea at codespeak.net) Date: Wed, 3 May 2006 10:41:31 +0200 (CEST) Subject: [pypy-svn] r26711 - pypy/extradoc/talk/agile2006 Message-ID: <20060503084131.CDC61100C6@code0.codespeak.net> Author: bea Date: Wed May 3 10:41:18 2006 New Revision: 26711 Modified: pypy/extradoc/talk/agile2006/draftpaper_agile2006.txt Log: minor clarifications based on feedback from Tres Seaver Modified: pypy/extradoc/talk/agile2006/draftpaper_agile2006.txt ============================================================================== --- pypy/extradoc/talk/agile2006/draftpaper_agile2006.txt (original) +++ pypy/extradoc/talk/agile2006/draftpaper_agile2006.txt Wed May 3 10:41:18 2006 @@ -4,7 +4,7 @@ .. raw:: latex - \author{Bea Duering} + \author{Beatrice During} \begin{abstract} PyPy is an Open Source project, partly funded by the European Union, employing @@ -340,7 +340,7 @@ in which developers pair off together in a room and focus on building a particular subsystem". -Tres Seaver from the Zope Corporation, one of the instigators of the sprint +Tres Seaver of the Zope Community, one of the instigators of the sprint method as it is used in the Python community says the following about how they evolved the method during 2001 and 2002: @@ -351,7 +351,7 @@ "as much XP as possible" for short, highly-focused sessions, with all active committers colocated." -Zope Corporation as well as other Python projects such as PyPy have seen that +The Zope community as well as other Python projects such as PyPy have seen that sprints have goals beyond the creation of software: - It helped to evolve the community through participation and hands-on contact @@ -376,6 +376,13 @@ to is "no overtime": as sprints often go far into the evening (or even the wee hours of the morning." +To summarize the results of this first try out of the methodology shows that +sprinting was the driver for making Zope3 a community-driven project: Zope +Corporation in fact ceded control over the development process to the new +"Zope3 core" group created via sprinting. Less than 2 years later the same effect +was to be found in the F/OSS project PyPy - the community evolved through +sprint driven development. + The sprint method, as well as key aspects of F/OSS supportive infrastructure and practices was established within the project before PyPy recieved it?s EU-funding. Thus, in the proposal,we put much emphasis on the methodology in From arigo at codespeak.net Wed May 3 10:55:55 2006 From: arigo at codespeak.net (arigo at codespeak.net) Date: Wed, 3 May 2006 10:55:55 +0200 (CEST) Subject: [pypy-svn] r26712 - in pypy/dist/pypy: objspace/cpy rpython/rctypes/tool rpython/rctypes/tool/test translator/goal Message-ID: <20060503085555.0BBAE100AC@code0.codespeak.net> Author: arigo Date: Wed May 3 10:55:53 2006 New Revision: 26712 Added: pypy/dist/pypy/rpython/rctypes/tool/test/test_compilemodule.py (contents, props changed) Modified: pypy/dist/pypy/objspace/cpy/capi.py pypy/dist/pypy/objspace/cpy/objspace.py pypy/dist/pypy/rpython/rctypes/tool/compilemodule.py pypy/dist/pypy/translator/goal/targetdemomodule.py Log: (pedronis, arigo) Finished tool/compilemodule.py. Now we can say: python compilemodule.py _demo Modified: pypy/dist/pypy/objspace/cpy/capi.py ============================================================================== --- pypy/dist/pypy/objspace/cpy/capi.py (original) +++ pypy/dist/pypy/objspace/cpy/capi.py Wed May 3 10:55:53 2006 @@ -94,6 +94,14 @@ PyObject_Type.argtypes = [W_Object] PyObject_Type.restype = W_Object +PyObject_Str = cpyapi.PyObject_Str +PyObject_Str.argtyps = [W_Object] +PyObject_Str.restype = W_Object + +PyObject_Repr = cpyapi.PyObject_Repr +PyObject_Repr.argtyps = [W_Object] +PyObject_Repr.restype = W_Object + ########################################################### # ____________________ Number Protocol ____________________ Modified: pypy/dist/pypy/objspace/cpy/objspace.py ============================================================================== --- pypy/dist/pypy/objspace/cpy/objspace.py (original) +++ pypy/dist/pypy/objspace/cpy/objspace.py Wed May 3 10:55:53 2006 @@ -12,6 +12,7 @@ self.options.geninterp = False self.w_int = W_Object(int) self.w_tuple = W_Object(tuple) + self.w_str = W_Object(str) self.w_None = W_Object(None) self.w_False = W_Object(False) self.w_True = W_Object(True) @@ -69,6 +70,8 @@ str_w = staticmethod(PyString_AsString) iter = staticmethod(PyObject_GetIter) type = staticmethod(PyObject_Type) + str = staticmethod(PyObject_Str) + repr = staticmethod(PyObject_Repr) add = staticmethod(PyNumber_Add) sub = staticmethod(PyNumber_Subtract) Modified: pypy/dist/pypy/rpython/rctypes/tool/compilemodule.py ============================================================================== --- pypy/dist/pypy/rpython/rctypes/tool/compilemodule.py (original) +++ pypy/dist/pypy/rpython/rctypes/tool/compilemodule.py Wed May 3 10:55:53 2006 @@ -7,14 +7,16 @@ """ import sys -import pypy.rpython.rctypes.implementation -from pypy.translator.goal.ann_override import PyPyAnnotatorPolicy -from pypy.rpython.rctypes.tool.cpyobjspace import CPyObjSpace -from pypy.translator.driver import TranslationDriver def compilemodule(modname): "Compile a PyPy module for CPython." + import pypy.rpython.rctypes.implementation + from pypy.objspace.cpy.objspace import CPyObjSpace + from pypy.objspace.cpy.wrappable import reraise + from pypy.objspace.cpy.ann_policy import CPyAnnotatorPolicy + from pypy.translator.driver import TranslationDriver + from pypy.interpreter.error import OperationError space = CPyObjSpace() ModuleClass = __import__('pypy.module.%s' % modname, @@ -22,7 +24,42 @@ module = ModuleClass(space, space.wrap(modname)) w_moduledict = module.getdict() - XXX in-progress, for now see translator/goal/targetdemomodule.py + def __init__(mod): + w_mod = CPyObjSpace.W_Object(mod) + try: +## space.appexec([w_mod, w_moduledict], +## '''(mod, newdict): +## old = mod.__dict__.copy() +## for key in ['__name__', '__doc__', 'RPythonError']: +## newdict[key] = old[key] +## newdict['__rpython__'] = old +## mod.__dict__.clear() +## mod.__dict__.update(newdict) +## ''') + # the same at interp-level: + w_moddict = space.getattr(w_mod, space.wrap('__dict__')) + w_old = space.call_method(w_moddict, 'copy') + space.call_method(w_moddict, 'clear') + space.setitem(w_moddict, space.wrap('__rpython__'), w_old) + for key in ['__name__', '__doc__', 'RPythonError']: + w_key = space.wrap(key) + try: + w1 = space.getitem(w_old, w_key) + except OperationError: + pass + else: + space.setitem(w_moddict, w_key, w1) + space.call_method(w_moddict, 'update', w_moduledict) + + except OperationError, e: + reraise(e) + + __init__.allow_someobjects = True + + driver = TranslationDriver(extmod_name=modname) + driver.setup(__init__, [object], policy=CPyAnnotatorPolicy(space)) + driver.proceed(['compile_c']) + return driver.cbuilder.c_ext_module if __name__ == '__main__': Added: pypy/dist/pypy/rpython/rctypes/tool/test/test_compilemodule.py ============================================================================== --- (empty file) +++ pypy/dist/pypy/rpython/rctypes/tool/test/test_compilemodule.py Wed May 3 10:55:53 2006 @@ -0,0 +1,8 @@ +import py +from pypy.rpython.rctypes.tool.compilemodule import compilemodule + +def test_demo(): + mod = compilemodule('_demo') + res = mod.measuretime(1000, long) + assert type(res) is int + py.test.raises(mod.DemoError, mod.measuretime, -5, long) Modified: pypy/dist/pypy/translator/goal/targetdemomodule.py ============================================================================== --- pypy/dist/pypy/translator/goal/targetdemomodule.py (original) +++ pypy/dist/pypy/translator/goal/targetdemomodule.py Wed May 3 10:55:53 2006 @@ -1,7 +1,9 @@ from pypy.module._demo import Module, demo from pypy.objspace.cpy.ann_policy import CPyAnnotatorPolicy from pypy.objspace.cpy.objspace import CPyObjSpace +from pypy.objspace.cpy.wrappable import reraise import pypy.rpython.rctypes.implementation +from pypy.interpreter.error import OperationError space = CPyObjSpace() @@ -10,8 +12,35 @@ def __init__(mod): w_mod = CPyObjSpace.W_Object(mod) - w_dict = space.getattr(w_mod, space.wrap('__dict__')) - space.call_method(w_dict, 'update', w_moduledict) + try: +## space.appexec([w_mod, w_moduledict], +## '''(mod, newdict): +## old = mod.__dict__.copy() +## mod.__dict__.clear() +## mod.__dict__['__rpython__'] = old +## for key in ['__name__', '__doc__', 'RPythonError']: +## if key in old: +## mod.__dict__[key] = old[key] +## mod.__dict__.update(newdict) +## ''') + + # the same at interp-level: + w_moddict = space.getattr(w_mod, space.wrap('__dict__')) + w_old = space.call_method(w_moddict, 'copy') + space.call_method(w_moddict, 'clear') + space.setitem(w_moddict, space.wrap('__rpython__'), w_old) + for key in ['__name__', '__doc__', 'RPythonError']: + w_key = space.wrap(key) + try: + w1 = space.getitem(w_old, w_key) + except OperationError: + pass + else: + space.setitem(w_moddict, w_key, w1) + space.call_method(w_moddict, 'update', w_moduledict) + + except OperationError, e: + reraise(e) __init__.allow_someobjects = True # _____ Define and setup target ___ From arigo at codespeak.net Wed May 3 11:02:50 2006 From: arigo at codespeak.net (arigo at codespeak.net) Date: Wed, 3 May 2006 11:02:50 +0200 (CEST) Subject: [pypy-svn] r26714 - in pypy/dist/pypy: annotation annotation/test rpython/lltypesystem rpython/test Message-ID: <20060503090250.BA252100BF@code0.codespeak.net> Author: arigo Date: Wed May 3 11:02:48 2006 New Revision: 26714 Modified: pypy/dist/pypy/annotation/annrpython.py pypy/dist/pypy/annotation/test/test_annrpython.py pypy/dist/pypy/annotation/unaryop.py pypy/dist/pypy/rpython/lltypesystem/rdict.py pypy/dist/pypy/rpython/test/test_remptydict.py Log: (pedronis, arigo) Support for iterating over empty lists and dicts. Modified: pypy/dist/pypy/annotation/annrpython.py ============================================================================== --- pypy/dist/pypy/annotation/annrpython.py (original) +++ pypy/dist/pypy/annotation/annrpython.py Wed May 3 11:02:48 2006 @@ -488,11 +488,12 @@ exits = [link for link in block.exits if link.exitcase is not None] - elif e.op.opname in ('simple_call', 'call_args'): + elif e.op.opname in ('simple_call', 'call_args', 'next'): # XXX warning, keep the name of the call operations in sync # with the flow object space. These are the operations for # which it is fine to always raise an exception. We then # swallow the BlockedInference and that's it. + # About 'next': see test_annotate_iter_empty_container(). return else: Modified: pypy/dist/pypy/annotation/test/test_annrpython.py ============================================================================== --- pypy/dist/pypy/annotation/test/test_annrpython.py (original) +++ pypy/dist/pypy/annotation/test/test_annrpython.py Wed May 3 11:02:48 2006 @@ -1975,6 +1975,23 @@ assert s.__class__ == annmodel.SomeObject assert s.knowntype == type + def test_annotate_iter_empty_container(self): + def f(): + n = 0 + d = {} + for x in []: n += x + for y in d: n += y + for z in d.iterkeys(): n += z + for s in d.itervalues(): n += s + for t, u in d.items(): n += t * u + for t, u in d.iteritems(): n += t * u + return n + + a = self.RPythonAnnotator() + s = a.build_types(f, []) + assert s.is_constant() + assert s.const == 0 + def g(n): return [0,1,2,n] Modified: pypy/dist/pypy/annotation/unaryop.py ============================================================================== --- pypy/dist/pypy/annotation/unaryop.py (original) +++ pypy/dist/pypy/annotation/unaryop.py Wed May 3 11:02:48 2006 @@ -7,7 +7,7 @@ SomeDict, SomeUnicodeCodePoint, SomeTuple, SomeImpossibleValue, \ SomeInstance, SomeBuiltin, SomeFloat, SomeIterator, SomePBC, \ SomeExternalObject, SomeTypedAddressAccess, SomeAddress, \ - SomeCTypesObject,\ + SomeCTypesObject, s_ImpossibleValue, \ unionof, set, missing_operation, add_knowntypedata from pypy.annotation.bookkeeper import getbookkeeper from pypy.annotation import builtin @@ -317,8 +317,13 @@ elif variant == 'values': return dct.dictdef.read_value() elif variant == 'items': - return SomeTuple((dct.dictdef.read_key(), - dct.dictdef.read_value())) + s_key = dct.dictdef.read_key() + s_value = dct.dictdef.read_value() + if (isinstance(s_key, SomeImpossibleValue) or + isinstance(s_value, SomeImpossibleValue)): + return s_ImpossibleValue + else: + return SomeTuple((s_key, s_value)) else: raise ValueError @@ -342,8 +347,7 @@ return getbookkeeper().newlist(dct.dictdef.read_value()) def method_items(dct): - return getbookkeeper().newlist(SomeTuple((dct.dictdef.read_key(), - dct.dictdef.read_value()))) + return getbookkeeper().newlist(dct.getanyitem('items')) def method_iterkeys(dct): return SomeIterator(dct, 'keys') @@ -388,7 +392,7 @@ def method_join(str, s_list): getbookkeeper().count("str_join", str) s_item = s_list.listdef.read_item() - if s_item == SomeImpossibleValue(): + if isinstance(s_item, SomeImpossibleValue): return immutablevalue("") return SomeString() Modified: pypy/dist/pypy/rpython/lltypesystem/rdict.py ============================================================================== --- pypy/dist/pypy/rpython/lltypesystem/rdict.py (original) +++ pypy/dist/pypy/rpython/lltypesystem/rdict.py Wed May 3 11:02:48 2006 @@ -614,7 +614,9 @@ index = index + 1 if entry.valid(): iter.index = index - if func is dum_items: + if RETURNTYPE is lltype.Void: + return None + elif func is dum_items: r = lltype.malloc(RETURNTYPE.TO) r.item0 = recast(RETURNTYPE.TO.item0, entry.key) r.item1 = recast(RETURNTYPE.TO.item1, entry.value) @@ -707,15 +709,16 @@ entry = entries[i] if entry.valid(): ELEM = lltype.typeOf(items).TO.OF - if func is dum_items: - r = lltype.malloc(ELEM.TO) - r.item0 = recast(ELEM.TO.item0, entry.key) - r.item1 = recast(ELEM.TO.item1, entry.value) - items[p] = r - elif func is dum_keys: - items[p] = recast(ELEM, entry.key) - elif func is dum_values: - items[p] = recast(ELEM, entry.value) + if ELEM is not lltype.Void: + if func is dum_items: + r = lltype.malloc(ELEM.TO) + r.item0 = recast(ELEM.TO.item0, entry.key) + r.item1 = recast(ELEM.TO.item1, entry.value) + items[p] = r + elif func is dum_keys: + items[p] = recast(ELEM, entry.key) + elif func is dum_values: + items[p] = recast(ELEM, entry.value) p += 1 i += 1 return res Modified: pypy/dist/pypy/rpython/test/test_remptydict.py ============================================================================== --- pypy/dist/pypy/rpython/test/test_remptydict.py (original) +++ pypy/dist/pypy/rpython/test/test_remptydict.py Wed May 3 11:02:48 2006 @@ -11,3 +11,17 @@ return bool(a.d1) or bool(a.d2) res = interpret(func, []) assert res is False + +def test_iterate_over_empty_dict(): + def f(): + n = 0 + d = {} + for x in []: n += x + for y in d: n += y + for z in d.iterkeys(): n += z + for s in d.itervalues(): n += s + for t, u in d.items(): n += t * u + for t, u in d.iteritems(): n += t * u + return n + res = interpret(f, []) + assert res == 0 From arigo at codespeak.net Wed May 3 12:32:50 2006 From: arigo at codespeak.net (arigo at codespeak.net) Date: Wed, 3 May 2006 12:32:50 +0200 (CEST) Subject: [pypy-svn] r26718 - in pypy/dist/pypy: rpython/memory translator/c translator/c/test Message-ID: <20060503103250.20884100B2@code0.codespeak.net> Author: arigo Date: Wed May 3 12:32:48 2006 New Revision: 26718 Modified: pypy/dist/pypy/rpython/memory/gctransform.py pypy/dist/pypy/translator/c/genc.py pypy/dist/pypy/translator/c/test/test_newgc.py Log: (pedronis, arigo) Fix two leaks in the refcounting gc policy. Modified: pypy/dist/pypy/rpython/memory/gctransform.py ============================================================================== --- pypy/dist/pypy/rpython/memory/gctransform.py (original) +++ pypy/dist/pypy/rpython/memory/gctransform.py Wed May 3 12:32:48 2006 @@ -259,6 +259,15 @@ # ---------------------------------------------------------------- +def ll_call_destructor(destrptr, destr_v): + try: + destrptr(destr_v) + except: + try: + os.write(2, "a destructor raised an exception, ignoring it\n") + except: + pass + def _static_deallocator_body_for_type(v, TYPE, depth=1): if isinstance(TYPE, lltype.Array): inner = list(_static_deallocator_body_for_type('v_%i'%depth, TYPE.OF, depth+1)) @@ -444,13 +453,7 @@ # refcount is at zero, temporarily bump it to 1: gcheader.signed[0] = 1 destr_v = cast_pointer(DESTR_ARG, v) - try: - destrptr(destr_v) - except: - try: - os.write(2, "a destructor raised an exception, ignoring it\\n") - except: - pass + ll_call_destructor(destrptr, destr_v) refcount = gcheader.signed[0] - 1 gcheader.signed[0] = refcount if refcount == 0: @@ -459,7 +462,9 @@ except: pass llop.gc_restore_exception(lltype.Void, exc_instance) - + pop_alive(exc_instance) + # XXX layering of exceptiontransform versus gcpolicy + """ % (body, ) else: call_del = None @@ -476,7 +481,7 @@ 'PTR_TYPE': lltype.Ptr(TYPE), 'DESTR_ARG': DESTR_ARG, 'EXC_INSTANCE_TYPE': self.translator.rtyper.exceptiondata.lltype_of_exception_value, - 'os': py.std.os} + 'll_call_destructor': ll_call_destructor} exec src in d this = d['ll_deallocator'] g, fptr = self.annotate_helper(this, [llmemory.Address], lltype.Void) @@ -627,14 +632,8 @@ EXC_INSTANCE_TYPE = self.translator.rtyper.exceptiondata.lltype_of_exception_value def ll_finalizer(addr): exc_instance = llop.gc_fetch_exception(EXC_INSTANCE_TYPE) - try: - v = llmemory.cast_adr_to_ptr(addr, DESTR_ARG) - destrptr(v) - except: - try: - os.write(2, "a destructor raised an exception, ignoring it\n") - except: - pass + v = llmemory.cast_adr_to_ptr(addr, DESTR_ARG) + ll_call_destructor(destrptr, v) llop.gc_restore_exception(lltype.Void, exc_instance) g, fptr = self.annotate_helper(ll_finalizer, [llmemory.Address], lltype.Void) else: Modified: pypy/dist/pypy/translator/c/genc.py ============================================================================== --- pypy/dist/pypy/translator/c/genc.py (original) +++ pypy/dist/pypy/translator/c/genc.py Wed May 3 12:32:48 2006 @@ -79,7 +79,7 @@ have___thread = None - def generate_source(self, db=None): + def generate_source(self, db=None, defines={}): assert self.c_source_filename is None translator = self.translator @@ -93,7 +93,7 @@ modulename = self.modulename targetdir = udir.ensure(modulename, dir=1) self.targetdir = targetdir - defines = {} + defines = defines.copy() # defines={'COUNT_OP_MALLOCS': 1} if CBuilder.have___thread is None: CBuilder.have___thread = check_under_under_thread() Modified: pypy/dist/pypy/translator/c/test/test_newgc.py ============================================================================== --- pypy/dist/pypy/translator/c/test/test_newgc.py (original) +++ pypy/dist/pypy/translator/c/test/test_newgc.py Wed May 3 12:32:48 2006 @@ -17,12 +17,20 @@ t.buildannotator().build_types(fn, inputtypes) t.buildrtyper().specialize() builder = genc.CExtModuleBuilder(t, fn, gcpolicy=gc.RefcountingGcPolicy) - builder.generate_source() + builder.generate_source(defines={'COUNT_OP_MALLOCS': 1}) builder.compile() builder.import_module() if conftest.option.view: t.view() - return builder.get_entry_point() + module = builder.c_ext_module + compiled_fn = builder.get_entry_point() + def checking_fn(*args, **kwds): + try: + return compiled_fn(*args, **kwds) + finally: + mallocs, frees = module.malloc_counters() + assert mallocs == frees + return checking_fn def test_something(): def f(): From arigo at codespeak.net Wed May 3 12:53:37 2006 From: arigo at codespeak.net (arigo at codespeak.net) Date: Wed, 3 May 2006 12:53:37 +0200 (CEST) Subject: [pypy-svn] r26719 - in pypy/dist/pypy: rpython/memory translator translator/c/test Message-ID: <20060503105337.19CFE100BB@code0.codespeak.net> Author: arigo Date: Wed May 3 12:53:36 2006 New Revision: 26719 Modified: pypy/dist/pypy/rpython/memory/gctransform.py pypy/dist/pypy/translator/c/test/test_genc.py pypy/dist/pypy/translator/c/test/test_newgc.py pypy/dist/pypy/translator/unsimplify.py Log: (pedronis, arigo) Fixed another rare leak in gctransform. Enabled malloc_counters() testing for most GenC tests. Modified: pypy/dist/pypy/rpython/memory/gctransform.py ============================================================================== --- pypy/dist/pypy/rpython/memory/gctransform.py (original) +++ pypy/dist/pypy/rpython/memory/gctransform.py Wed May 3 12:53:36 2006 @@ -4,6 +4,7 @@ from pypy.objspace.flow.model import SpaceOperation, Variable, Constant, \ c_last_exception, FunctionGraph, Block, Link, checkgraph from pypy.translator.unsimplify import insert_empty_block +from pypy.translator.unsimplify import insert_empty_startblock from pypy.translator.translator import graphof from pypy.translator.backendopt.support import var_needsgc, needs_conservative_livevar_calculation from pypy.translator.backendopt import graphanalyze @@ -67,7 +68,18 @@ return self.seen_graphs[graph] = True self.links_to_split = {} # link -> vars to pop_alive across the link - + + # add push_alives at the beginning of the graph + newops = [] + for var in graph.startblock.inputargs: + if var_needsgc(var): + newops.extend(self.push_alive(var)) + if newops: # only to check if we are going to add any operation at all + insert_empty_startblock(None, graph) + for var in graph.startblock.inputargs: + if var_needsgc(var): + graph.startblock.operations.extend(self.push_alive(var)) + for block in graph.iterblocks(): self.transform_block(block) for link, livecounts in self.links_to_split.iteritems(): @@ -104,10 +116,6 @@ newops = [] livevars = [var for var in block.inputargs if var_needsgc(var)] newops = [] - if block.isstartblock: - for var in block.inputargs: - if var_needsgc(var): - newops.extend(self.push_alive(var)) # XXX this is getting obscure. Maybe we should use the basic # graph-transforming capabilities of the RTyper instead, as we # seem to run into all the same problems as the ones we already 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 Wed May 3 12:53:36 2006 @@ -46,10 +46,11 @@ t.view() compiled_fn = getattr(module, entrypoint) def checking_fn(*args, **kwds): - res = compiled_fn(*args, **kwds) - mallocs, frees = module.malloc_counters() - assert mallocs == frees - return res + try: + return compiled_fn(*args, **kwds) + finally: + mallocs, frees = module.malloc_counters() + assert mallocs == frees return checking_fn def test_func_as_pyobject(): Modified: pypy/dist/pypy/translator/c/test/test_newgc.py ============================================================================== --- pypy/dist/pypy/translator/c/test/test_newgc.py (original) +++ pypy/dist/pypy/translator/c/test/test_newgc.py Wed May 3 12:53:36 2006 @@ -12,8 +12,9 @@ from pypy import conftest -def compile_func(fn, inputtypes): - t = TranslationContext() +def compile_func(fn, inputtypes, t=None): + if t is None: + t = TranslationContext() t.buildannotator().build_types(fn, inputtypes) t.buildrtyper().specialize() builder = genc.CExtModuleBuilder(t, fn, gcpolicy=gc.RefcountingGcPolicy) @@ -193,6 +194,33 @@ res = fn(1) assert res == 1 +def test_wrong_startblock_incref(): + class B(object): + pass + def g(b): + while True: + b.x -= 10 + if b.x < 0: + return b.x + def f(n): + b = B() + b.x = n + return g(b) + + # XXX obscure: remove the first empty block in the graph of 'g' + t = TranslationContext() + graph = t.buildflowgraph(g) + assert graph.startblock.operations == [] + graph.startblock = graph.startblock.exits[0].target + graph.startblock.isstartblock = True + from pypy.objspace.flow.model import checkgraph + checkgraph(graph) + t._prebuilt_graphs[g] = graph + + fn = compile_func(f, [int], t) + res = fn(112) + assert res == -8 + class Weakrefable(object): __lifeline__ = None Modified: pypy/dist/pypy/translator/unsimplify.py ============================================================================== --- pypy/dist/pypy/translator/unsimplify.py (original) +++ pypy/dist/pypy/translator/unsimplify.py Wed May 3 12:53:36 2006 @@ -35,6 +35,14 @@ link.target = newblock return newblock +def insert_empty_startblock(translator, graph): + vars = [copyvar(translator, v) for v in graph.startblock.inputargs] + newblock = Block(vars) + newblock.closeblock(Link(vars, graph.startblock)) + graph.startblock.isstartblock = False + graph.startblock = newblock + graph.startblock.isstartblock = True + def split_block(translator, block, index): """return a link where prevblock is the block leading up but excluding the index'th operation and target is a new block with the neccessary variables From ale at codespeak.net Wed May 3 13:53:13 2006 From: ale at codespeak.net (ale at codespeak.net) Date: Wed, 3 May 2006 13:53:13 +0200 (CEST) Subject: [pypy-svn] r26720 - pypy/dist/pypy/rpython/rctypes/socketmodule Message-ID: <20060503115313.8EC2E100AB@code0.codespeak.net> Author: ale Date: Wed May 3 13:53:12 2006 New Revision: 26720 Modified: pypy/dist/pypy/rpython/rctypes/socketmodule/ctypes_socket.py Log: Trying to avoid adding conversion from StringRepr to VoidPointerRepr Modified: pypy/dist/pypy/rpython/rctypes/socketmodule/ctypes_socket.py ============================================================================== --- pypy/dist/pypy/rpython/rctypes/socketmodule/ctypes_socket.py (original) +++ pypy/dist/pypy/rpython/rctypes/socketmodule/ctypes_socket.py Wed May 3 13:53:12 2006 @@ -128,7 +128,7 @@ ('h_aliases', POINTER(c_char_p)), ('h_addrtype', c_int), ('h_length', c_int), - ('h_addr_list', POINTER(POINTER(c_char))) + ('h_addr_list', POINTER(c_char_p)) ]) @@ -320,11 +320,11 @@ getaddrinfo.restype = c_int gethostname = socketdll.gethostname -gethostname.argtypes = [POINTER(c_char), c_int] +gethostname.argtypes = [c_char_p, c_int] gethostname.restype = c_int gethostbyname = socketdll.gethostbyname -gethostbyname.argtypes = [POINTER(c_char)] +gethostbyname.argtypes = [c_char_p] gethostbyname.restype = POINTER(cConfig.hostent) gethostbyaddr = socketdll.gethostbyaddr From ale at codespeak.net Wed May 3 13:54:15 2006 From: ale at codespeak.net (ale at codespeak.net) Date: Wed, 3 May 2006 13:54:15 +0200 (CEST) Subject: [pypy-svn] r26721 - pypy/dist/pypy/module/_socket Message-ID: <20060503115415.67386100AB@code0.codespeak.net> Author: ale Date: Wed May 3 13:54:14 2006 New Revision: 26721 Modified: pypy/dist/pypy/module/_socket/interp_socket.py Log: Small bugfixes - still it does not translate Modified: pypy/dist/pypy/module/_socket/interp_socket.py ============================================================================== --- pypy/dist/pypy/module/_socket/interp_socket.py (original) +++ pypy/dist/pypy/module/_socket/interp_socket.py Wed May 3 13:54:14 2006 @@ -628,9 +628,9 @@ except: _c.freeaddrinfo(res) raise - res = space.newlist(result) + result = space.newlist(result) _c.freeaddrinfo(res) - return res + return result getaddrinfo.unwrap_spec = [ObjSpace, W_Root, W_Root, int, int, int, int] def getnameinfo(space, w_sockaddr, flags): @@ -675,9 +675,10 @@ hostbuf = ctypes.create_string_buffer(_c.NI_MAXHOST) portbuf = ctypes.create_string_buffer(_c.NI_MAXSERV) + maxhost = _c.size_t(_c.NI_MAXHOST) error = _c.getnameinfo(res.contents.ai_addr, res.contents.ai_addrlen, - hostbuf, _c.NI_MAXHOST, - portbuf, _c.NI_MAXSERV, flags) + hostbuf, maxhost, + portbuf, _c.size_t(_c.NI_MAXSERV), flags) if res: _c.freeaddrinfo(res) From arigo at codespeak.net Wed May 3 16:17:04 2006 From: arigo at codespeak.net (arigo at codespeak.net) Date: Wed, 3 May 2006 16:17:04 +0200 (CEST) Subject: [pypy-svn] r26724 - pypy/dist/pypy/rpython/memory Message-ID: <20060503141704.F0BEF10094@code0.codespeak.net> Author: arigo Date: Wed May 3 16:17:03 2006 New Revision: 26724 Modified: pypy/dist/pypy/rpython/memory/gctransform.py Log: * Preserve the annotation on the graph's inputargs. * More robust: don't insert the push_alives in a block that will again be gc-transformed. Modified: pypy/dist/pypy/rpython/memory/gctransform.py ============================================================================== --- pypy/dist/pypy/rpython/memory/gctransform.py (original) +++ pypy/dist/pypy/rpython/memory/gctransform.py Wed May 3 16:17:03 2006 @@ -75,10 +75,7 @@ if var_needsgc(var): newops.extend(self.push_alive(var)) if newops: # only to check if we are going to add any operation at all - insert_empty_startblock(None, graph) - for var in graph.startblock.inputargs: - if var_needsgc(var): - graph.startblock.operations.extend(self.push_alive(var)) + insert_empty_startblock(self.translator, graph) for block in graph.iterblocks(): self.transform_block(block) @@ -116,6 +113,9 @@ newops = [] livevars = [var for var in block.inputargs if var_needsgc(var)] newops = [] + if block.isstartblock: + for var in livevars: + newops.extend(self.push_alive(var)) # XXX this is getting obscure. Maybe we should use the basic # graph-transforming capabilities of the RTyper instead, as we # seem to run into all the same problems as the ones we already From arigo at codespeak.net Wed May 3 18:36:28 2006 From: arigo at codespeak.net (arigo at codespeak.net) Date: Wed, 3 May 2006 18:36:28 +0200 (CEST) Subject: [pypy-svn] r26730 - in pypy/dist/pypy: rpython rpython/memory rpython/memory/test translator Message-ID: <20060503163628.4F30510092@code0.codespeak.net> Author: arigo Date: Wed May 3 18:36:25 2006 New Revision: 26730 Modified: pypy/dist/pypy/rpython/annlowlevel.py pypy/dist/pypy/rpython/memory/gctransform.py pypy/dist/pypy/rpython/memory/test/test_gctransform.py pypy/dist/pypy/rpython/rspecialcase.py pypy/dist/pypy/translator/unsimplify.py Log: This is originally a fix for a segfault in the stackless transformer, which is worked around by optimizing away increfs/decrefs. Now the RefcountingGCTransformer delays the increfs on input arguments, and keeps their reference as borrowed for as long as possible (which is for the whole function unless they are merged with other values). As a side clean-up, removed 'compute_ll_ops' (rev 22858) because I needed to do something also when annotating ll_pop_alive(), not just when specializing it. Now it's just an ExtRegistry entry. Modified: pypy/dist/pypy/rpython/annlowlevel.py ============================================================================== --- pypy/dist/pypy/rpython/annlowlevel.py (original) +++ pypy/dist/pypy/rpython/annlowlevel.py Wed May 3 18:36:25 2006 @@ -47,10 +47,6 @@ override_do_imports_immediately = True def default_specialize(pol, funcdesc, args_s): - if hasattr(funcdesc, 'pyobj') and hasattr(funcdesc.pyobj, 'llresult'): - # XXX bug mwh to write some tests for this stuff - funcdesc.overridden = True - return annmodel.lltype_to_annotation(funcdesc.pyobj.llresult) key = [] new_args_s = [] for s_obj in args_s: @@ -154,6 +150,10 @@ return repr.convert_const(obj) def finish(self): + self.finish_annotate() + self.finish_rtype() + + def finish_annotate(self): # push all the graphs into the annotator's pending blocks dict at once rtyper = self.rtyper ann = rtyper.annotator @@ -172,6 +172,9 @@ "originally specified: %r\n" " found by annotating: %r" % (graph, s_result, s_real_result)) + + def finish_rtype(self): + rtyper = self.rtyper rtyper.type_system.perform_normalizations(rtyper) for r in self.delayedreprs: r.set_setup_delayed(False) Modified: pypy/dist/pypy/rpython/memory/gctransform.py ============================================================================== --- pypy/dist/pypy/rpython/memory/gctransform.py (original) +++ pypy/dist/pypy/rpython/memory/gctransform.py Wed May 3 18:36:25 2006 @@ -5,13 +5,17 @@ c_last_exception, FunctionGraph, Block, Link, checkgraph from pypy.translator.unsimplify import insert_empty_block from pypy.translator.unsimplify import insert_empty_startblock +from pypy.translator.unsimplify import starts_with_empty_block +from pypy.translator.unsimplify import remove_empty_startblock from pypy.translator.translator import graphof from pypy.translator.backendopt.support import var_needsgc, needs_conservative_livevar_calculation from pypy.translator.backendopt import graphanalyze +from pypy.translator.backendopt.ssa import DataFlowFamilyBuilder from pypy.annotation import model as annmodel from pypy.rpython import rmodel, rptr, annlowlevel, typesystem from pypy.rpython.memory import gc, lladdress from pypy.rpython.annlowlevel import MixLevelHelperAnnotator +from pypy.rpython.extregistry import ExtRegistryEntry import sets, os NEVER_RAISING_OPS = ['gc_protect', 'gc_unprotect'] @@ -69,16 +73,13 @@ self.seen_graphs[graph] = True self.links_to_split = {} # link -> vars to pop_alive across the link - # add push_alives at the beginning of the graph - newops = [] - for var in graph.startblock.inputargs: - if var_needsgc(var): - newops.extend(self.push_alive(var)) - if newops: # only to check if we are going to add any operation at all + # for sanity, we need an empty block at the start of the graph + if not starts_with_empty_block(graph): insert_empty_startblock(self.translator, graph) + is_borrowed = self.compute_borrowed_vars(graph) for block in graph.iterblocks(): - self.transform_block(block) + self.transform_block(block, is_borrowed) for link, livecounts in self.links_to_split.iteritems(): newops = [] for var, livecount in livecounts.iteritems(): @@ -87,15 +88,36 @@ for i in range(-livecount): newops.extend(self.push_alive(var)) if newops: - if len(link.prevblock.exits) == 1: + if link.prevblock.exitswitch is None: link.prevblock.operations.extend(newops) else: - insert_empty_block(None, link, newops) + insert_empty_block(self.translator, link, newops) + + # remove the empty block at the start of the graph, which should + # still be empty (but let's check) + if starts_with_empty_block(graph): + remove_empty_startblock(graph) self.links_to_split = None v = Variable('vanishing_exc_value') v.concretetype = self.get_lltype_of_exception_value() graph.exc_cleanup = (v, self.pop_alive(v)) + return is_borrowed # xxx for tests only + + def compute_borrowed_vars(self, graph): + # the input args are borrowed, and stay borrowed for as long as they + # are not merged with other values. + var_families = DataFlowFamilyBuilder(graph).get_variable_families() + borrowed_reps = {} + for v in graph.getargs(): + borrowed_reps[var_families.find_rep(v)] = True + # no support for returning borrowed values so far + retvar = graph.getreturnvar() + + def is_borrowed(v1): + return (var_families.find_rep(v1) in borrowed_reps + and v1 is not retvar) + return is_borrowed def inline_helpers(self, graph): if self.inline: @@ -109,13 +131,11 @@ pass checkgraph(graph) - def transform_block(self, block): + def transform_block(self, block, is_borrowed): newops = [] - livevars = [var for var in block.inputargs if var_needsgc(var)] + livevars = [var for var in block.inputargs if var_needsgc(var) + and not is_borrowed(var)] newops = [] - if block.isstartblock: - for var in livevars: - newops.extend(self.push_alive(var)) # XXX this is getting obscure. Maybe we should use the basic # graph-transforming capabilities of the RTyper instead, as we # seem to run into all the same problems as the ones we already @@ -137,7 +157,8 @@ elif op.opname not in ('direct_call', 'indirect_call'): lst = list(self.push_alive(op.result)) newops.extend(lst) - livevars.append(op.result) + if not is_borrowed(op.result): + livevars.append(op.result) if len(block.exits) == 0: # everything is fine already for returnblocks and exceptblocks pass @@ -150,11 +171,14 @@ newops.extend(self.pop_alive(var)) for link in block.exits: livecounts = dict.fromkeys(sets.Set(livevars) - deadinallexits, 1) - for v in link.args: + for v, v2 in zip(link.args, link.target.inputargs): + if is_borrowed(v2): + continue if v in livecounts: livecounts[v] -= 1 elif var_needsgc(v): - assert isinstance(v, Constant) + # 'v' is typically a Constant here, but it can be + # a borrowed variable going into a non-borrowed one livecounts[v] = -1 self.links_to_split[link] = livecounts if newops: @@ -253,9 +277,11 @@ return Constant(ptr, lltype.Ptr(lltype.FuncType(ll_args, ll_result))) def finish(self): + if self.translator is not None: + self.mixlevelannotator.finish_annotate() self.finished = True if self.translator is not None: - self.mixlevelannotator.finish() + self.mixlevelannotator.finish_rtype() class MinimalGCTransformer(GCTransformer): def push_alive(self, var): @@ -265,7 +291,40 @@ return [] - # ---------------------------------------------------------------- +# ---------------------------------------------------------------- + +class LLTransformerOp(object): + """Objects that can be called in ll functions. + Their calls are replaced by a simple operation of the GC transformer, + e.g. ll_pop_alive. + """ + def __init__(self, transformer, opname): + self.transformer = transformer + self.opname = opname + +class LLTransformerOpEntry(ExtRegistryEntry): + "Annotation and specialization of LLTransformerOp() instances." + _type_ = LLTransformerOp + + def compute_result_annotation(self, s_arg): + assert isinstance(s_arg, annmodel.SomePtr) + PTRTYPE = s_arg.ll_ptrtype + if PTRTYPE.TO is not lltype.PyObject: + # look for and annotate a dynamic deallocator if necessary; + # doing so implicitly in specialize_call() is too late. + op = self.instance # the LLTransformerOp instance + op.transformer.dynamic_deallocation_funcptr_for_type(PTRTYPE.TO) + return annmodel.s_None + + def specialize_call(self, hop): + op = self.instance # the LLTransformerOp instance + meth = getattr(op.transformer, op.opname) + newops = meth(hop.args_v[0]) + hop.llops.extend(newops) + hop.exception_cannot_occur() + return hop.inputconst(hop.r_result.lowleveltype, hop.s_result.const) + +# ---------------------------------------------------------------- def ll_call_destructor(destrptr, destr_v): try: @@ -427,14 +486,6 @@ if TYPE in self.static_deallocator_funcptrs: return self.static_deallocator_funcptrs[TYPE] #print_call_chain(self) - def compute_pop_alive_ll_ops(hop): - hop.llops.extend(self.pop_alive(hop.args_v[1])) - hop.exception_cannot_occur() - return hop.inputconst(hop.r_result.lowleveltype, hop.s_result.const) - def ll_pop_alive(var): - pass - ll_pop_alive.compute_ll_ops = compute_pop_alive_ll_ops - ll_pop_alive.llresult = lltype.Void rtti = self.get_rtti(TYPE) if rtti is not None and hasattr(rtti._obj, 'destructor_funcptr'): @@ -479,7 +530,7 @@ body = '\n'.join(_static_deallocator_body_for_type('v', TYPE)) src = ('def ll_deallocator(addr):\n v = cast_adr_to_ptr(addr, PTR_TYPE)\n' + body + '\n llop.gc_free(lltype.Void, addr)\n') - d = {'pop_alive': ll_pop_alive, + d = {'pop_alive': LLTransformerOp(self, 'pop_alive'), 'llop': llop, 'lltype': lltype, 'destrptr': destrptr, @@ -606,15 +657,7 @@ def finalizer_funcptr_for_type(self, TYPE): if TYPE in self.finalizer_funcptrs: return self.finalizer_funcptrs[TYPE] - - def compute_pop_alive_ll_ops(hop): - hop.llops.extend(self.pop_alive(hop.args_v[1])) - return hop.inputconst(hop.r_result.lowleveltype, hop.s_result.const) - def ll_pop_alive(var): - pass - ll_pop_alive.compute_ll_ops = compute_pop_alive_ll_ops - ll_pop_alive.llresult = lltype.Void - + rtti = self.get_rtti(TYPE) if rtti is not None and hasattr(rtti._obj, 'destructor_funcptr'): destrptr = rtti._obj.destructor_funcptr @@ -628,7 +671,7 @@ raise Exception("can't mix PyObjects and __del__ with Boehm") static_body = '\n'.join(_static_deallocator_body_for_type('v', TYPE)) - d = {'pop_alive':ll_pop_alive, + d = {'pop_alive': LLTransformerOp(self, 'pop_alive'), 'PTR_TYPE':lltype.Ptr(TYPE), 'cast_adr_to_ptr': llmemory.cast_adr_to_ptr} src = ("def ll_finalizer(addr):\n" Modified: pypy/dist/pypy/rpython/memory/test/test_gctransform.py ============================================================================== --- pypy/dist/pypy/rpython/memory/test/test_gctransform.py (original) +++ pypy/dist/pypy/rpython/memory/test/test_gctransform.py Wed May 3 18:36:25 2006 @@ -11,7 +11,7 @@ import py -def checkblock(block): +def checkblock(block, is_borrowed): if block.operations == (): # a return/exception block -- don't want to think about them # (even though the test passes for somewhat accidental reasons) @@ -19,7 +19,9 @@ if block.isstartblock: refs_in = 0 else: - refs_in = len([v for v in block.inputargs if isinstance(v, Variable) and var_needsgc(v)]) + refs_in = len([v for v in block.inputargs if isinstance(v, Variable) + and var_needsgc(v) + and not is_borrowed(v)]) push_alives = len([op for op in block.operations if op.opname == 'gc_push_alive']) pyobj_push_alives = len([op for op in block.operations @@ -43,7 +45,10 @@ return for link in block.exits: assert block.exitswitch is not c_last_exception - refs_out = len([v for v in link.args if var_needsgc(v)]) + refs_out = 0 + for v2 in link.target.inputargs: + if var_needsgc(v2) and not is_borrowed(v2): + refs_out += 1 pyobj_pushes = pyobj_push_alives + implicit_pyobj_pushalives nonpyobj_pushes = push_alives + nonpyobj_gc_returning_calls assert refs_in + pyobj_pushes + nonpyobj_pushes == pop_alives + pyobj_pop_alives + refs_out @@ -67,14 +72,16 @@ etrafo = ExceptionTransformer(t) etrafo.transform_completely() transformer = transformcls(t) - transformer.transform(t.graphs) + graphs_borrowed = {} + for graph in t.graphs: + graphs_borrowed[graph] = transformer.transform_graph(graph) if conftest.option.view: t.view() t.checkgraphs() if check: - for graph in t.graphs: + for graph, is_borrowed in graphs_borrowed.iteritems(): for block in graph.iterblocks(): - checkblock(block) + checkblock(block, is_borrowed) return t, transformer def test_simple(): Modified: pypy/dist/pypy/rpython/rspecialcase.py ============================================================================== --- pypy/dist/pypy/rpython/rspecialcase.py (original) +++ pypy/dist/pypy/rpython/rspecialcase.py Wed May 3 18:36:25 2006 @@ -7,9 +7,6 @@ if len(s_pbc.descriptions) != 1: raise TyperError("not monomorphic call_specialcase") desc, = s_pbc.descriptions - if hasattr(desc.pyobj, 'compute_ll_ops'): - # XXX bug mwh to write some tests for this stuff - return desc.pyobj.compute_ll_ops(hop) tag = desc.pyobj._annspecialcase_ if not tag.startswith("override:"): raise TyperError("call_specialcase only supports 'override:' functions") Modified: pypy/dist/pypy/translator/unsimplify.py ============================================================================== --- pypy/dist/pypy/translator/unsimplify.py (original) +++ pypy/dist/pypy/translator/unsimplify.py Wed May 3 18:36:25 2006 @@ -43,6 +43,16 @@ graph.startblock = newblock graph.startblock.isstartblock = True +def starts_with_empty_block(graph): + return (not graph.startblock.operations + and graph.startblock.exitswitch is None + and graph.startblock.exits[0].args == graph.getargs()) + +def remove_empty_startblock(graph): + graph.startblock.isstartblock = False + graph.startblock = graph.startblock.exits[0].target + graph.startblock.isstartblock = True + def split_block(translator, block, index): """return a link where prevblock is the block leading up but excluding the index'th operation and target is a new block with the neccessary variables From cfbolz at codespeak.net Wed May 3 18:42:56 2006 From: cfbolz at codespeak.net (cfbolz at codespeak.net) Date: Wed, 3 May 2006 18:42:56 +0200 (CEST) Subject: [pypy-svn] r26731 - pypy/dist/pypy/rpython/memory Message-ID: <20060503164256.CC03710092@code0.codespeak.net> Author: cfbolz Date: Wed May 3 18:42:51 2006 New Revision: 26731 Modified: pypy/dist/pypy/rpython/memory/gctransform.py Log: remove unused global (which comes from before the introduction of the exception transformer) Modified: pypy/dist/pypy/rpython/memory/gctransform.py ============================================================================== --- pypy/dist/pypy/rpython/memory/gctransform.py (original) +++ pypy/dist/pypy/rpython/memory/gctransform.py Wed May 3 18:42:51 2006 @@ -18,9 +18,6 @@ from pypy.rpython.extregistry import ExtRegistryEntry import sets, os -NEVER_RAISING_OPS = ['gc_protect', 'gc_unprotect'] - - def var_ispyobj(var): if hasattr(var, 'concretetype'): if isinstance(var.concretetype, lltype.Ptr): From dialtone at codespeak.net Wed May 3 18:53:26 2006 From: dialtone at codespeak.net (dialtone at codespeak.net) Date: Wed, 3 May 2006 18:53:26 +0200 (CEST) Subject: [pypy-svn] r26732 - in pypy/dist/pypy/translator/cl: . test Message-ID: <20060503165326.1DB1510092@code0.codespeak.net> Author: dialtone Date: Wed May 3 18:53:24 2006 New Revision: 26732 Modified: pypy/dist/pypy/translator/cl/gencl.py pypy/dist/pypy/translator/cl/opformatter.py pypy/dist/pypy/translator/cl/test/test_cltrans.py Log: pass new version of half_of_n, avoid undeclared free variable style warning Modified: pypy/dist/pypy/translator/cl/gencl.py ============================================================================== --- pypy/dist/pypy/translator/cl/gencl.py (original) +++ pypy/dist/pypy/translator/cl/gencl.py Wed May 3 18:53:24 2006 @@ -109,12 +109,13 @@ # const.concretetype is Instance if const in self.declarations: return self.declarations[const][0] - name = "const" + str(self.constcount) + name = "+const" + str(self.constcount) + "+" INST = dynamicType(const.value) self.declare_class(INST) inst = oodowncast(INST, const.value) cls = clrepr(INST) const_declaration = [] + const_declaration.append("(defvar %s nil)" % clrepr(name, True)) const_declaration.append("(setf %s (make-instance %s))" % (clrepr(name, True), clrepr(cls, True))) fields = INST._allfields() Modified: pypy/dist/pypy/translator/cl/opformatter.py ============================================================================== --- pypy/dist/pypy/translator/cl/opformatter.py (original) +++ pypy/dist/pypy/translator/cl/opformatter.py Wed May 3 18:53:24 2006 @@ -34,6 +34,7 @@ op_cast_int_to_char = make_unary_op("code-char") op_cast_float_to_int = make_unary_op("truncate") op_cast_int_to_float = make_unary_op("float") + op_int_neg = make_unary_op("not") def make_binary_op(cl_op): def binary_op(self, result, arg1, arg2): @@ -47,6 +48,7 @@ op_int_eq = make_binary_op("=") op_int_gt = make_binary_op(">") op_int_ge = make_binary_op(">=") + op_int_ne = make_binary_op("/=") op_int_lt = make_binary_op("<") op_int_le = make_binary_op("<=") op_int_and = make_binary_op("logand") @@ -165,6 +167,12 @@ def ll_setitem_fast(self, index, value): return "(setf (aref %s %s) %s)" % (self.obj, index, value) + + def _ll_resize_le(self, size): + return "(adjust-array %s %s)" % (self.obj, size) + + def _ll_resize_ge(self, size): + return "(adjust-array %s %s)" % (self.obj, size) def _ll_resize(self, size): return "(adjust-array %s %s)" % (self.obj, size) Modified: pypy/dist/pypy/translator/cl/test/test_cltrans.py ============================================================================== --- pypy/dist/pypy/translator/cl/test/test_cltrans.py (original) +++ pypy/dist/pypy/translator/cl/test/test_cltrans.py Wed May 3 18:53:24 2006 @@ -131,8 +131,19 @@ assert cl_builtinusage() == 4 def test_slice(): - py.test.skip("either this is not RPython or gencl has something horribly wrong") - cl_half = make_cl_func(t.half_of_n, [int]) + def half_of_n(n=int): + """Slice test""" + i = 0 + lst = range(n) + while lst: + lst = lst[1:] + if len(lst) > 0: + lst.pop() + i = i + 1 + return i + cl_half = make_cl_func(half_of_n, [int]) + assert cl_half(2) == 1 + assert cl_half(4) == 2 assert cl_half(10) == 5 def test_powerset(): From ale at codespeak.net Wed May 3 18:57:09 2006 From: ale at codespeak.net (ale at codespeak.net) Date: Wed, 3 May 2006 18:57:09 +0200 (CEST) Subject: [pypy-svn] r26733 - pypy/dist/pypy/module/_socket Message-ID: <20060503165709.997D310094@code0.codespeak.net> Author: ale Date: Wed May 3 18:57:08 2006 New Revision: 26733 Modified: pypy/dist/pypy/module/_socket/interp_socket.py Log: make sure indexes are nonnegative and that pointers dont get MIXEDMEMORYOWNERSHIP Modified: pypy/dist/pypy/module/_socket/interp_socket.py ============================================================================== --- pypy/dist/pypy/module/_socket/interp_socket.py (original) +++ pypy/dist/pypy/module/_socket/interp_socket.py Wed May 3 18:57:08 2006 @@ -476,9 +476,12 @@ number = number * 16 + (char_ord - A_ord) + 10 pos += 1 elif char == ".": - if i - pos == 0: + new_pos = i - pos + if new_pos == 0: return "" - packed_v4 = inet_pton_ipv4(space, ip[i - pos:]) + packed_v4 = "" + if new_pos > 0: + packed_v4 = inet_pton_ipv4(space, ip[new_pos:]) if len(packed_v4) == 0: return "" packed += packed_v4 @@ -608,7 +611,26 @@ raise w_get_socketgaierror(space, None, retval) result = [] - next = res + next = None + if res: + info = res.contents + next = info.ai_next + try: + w_family = space.wrap(info.ai_family) + w_socktype = space.wrap(info.ai_socktype) + w_proto = space.wrap(info.ai_protocol) + if info.ai_canonname: + w_canonname = space.wrap(info.ai_canonname) + else: + w_canonname = space.wrap('') + w_addr = w_makesockaddr(space, + _c.cast(info.ai_addr, _c.sockaddr_ptr), + info.ai_addrlen, info.ai_protocol) + result.append(space.newtuple([w_family, w_socktype, w_proto, + w_canonname, w_addr])) + except: + _c.freeaddrinfo(res) + raise while next: info = next.contents next = info.ai_next From arigo at codespeak.net Wed May 3 18:57:14 2006 From: arigo at codespeak.net (arigo at codespeak.net) Date: Wed, 3 May 2006 18:57:14 +0200 (CEST) Subject: [pypy-svn] r26734 - pypy/dist/pypy/rpython/memory Message-ID: <20060503165714.92E9D100A7@code0.codespeak.net> Author: arigo Date: Wed May 3 18:57:11 2006 New Revision: 26734 Modified: pypy/dist/pypy/rpython/memory/gctransform.py Log: Crashed the Boehm gc transformer (in the presence of a __del__). Modified: pypy/dist/pypy/rpython/memory/gctransform.py ============================================================================== --- pypy/dist/pypy/rpython/memory/gctransform.py (original) +++ pypy/dist/pypy/rpython/memory/gctransform.py Wed May 3 18:57:11 2006 @@ -295,28 +295,28 @@ Their calls are replaced by a simple operation of the GC transformer, e.g. ll_pop_alive. """ - def __init__(self, transformer, opname): - self.transformer = transformer - self.opname = opname + def __init__(self, transformer_method, see_type=None): + self.transformer_method = transformer_method + self.see_type = see_type class LLTransformerOpEntry(ExtRegistryEntry): "Annotation and specialization of LLTransformerOp() instances." _type_ = LLTransformerOp def compute_result_annotation(self, s_arg): - assert isinstance(s_arg, annmodel.SomePtr) - PTRTYPE = s_arg.ll_ptrtype - if PTRTYPE.TO is not lltype.PyObject: - # look for and annotate a dynamic deallocator if necessary; - # doing so implicitly in specialize_call() is too late. - op = self.instance # the LLTransformerOp instance - op.transformer.dynamic_deallocation_funcptr_for_type(PTRTYPE.TO) + op = self.instance # the LLTransformerOp instance + if op.see_type is not None: + assert isinstance(s_arg, annmodel.SomePtr) + PTRTYPE = s_arg.ll_ptrtype + if PTRTYPE.TO is not lltype.PyObject: + # look for and annotate a dynamic deallocator if necessary; + # doing so implicitly in specialize_call() is too late. + op.see_type(PTRTYPE.TO) return annmodel.s_None def specialize_call(self, hop): op = self.instance # the LLTransformerOp instance - meth = getattr(op.transformer, op.opname) - newops = meth(hop.args_v[0]) + newops = op.transformer_method(hop.args_v[0]) hop.llops.extend(newops) hop.exception_cannot_occur() return hop.inputconst(hop.r_result.lowleveltype, hop.s_result.const) @@ -527,7 +527,8 @@ body = '\n'.join(_static_deallocator_body_for_type('v', TYPE)) src = ('def ll_deallocator(addr):\n v = cast_adr_to_ptr(addr, PTR_TYPE)\n' + body + '\n llop.gc_free(lltype.Void, addr)\n') - d = {'pop_alive': LLTransformerOp(self, 'pop_alive'), + d = {'pop_alive': LLTransformerOp(self.pop_alive, + self.dynamic_deallocation_funcptr_for_type), 'llop': llop, 'lltype': lltype, 'destrptr': destrptr, @@ -668,7 +669,7 @@ raise Exception("can't mix PyObjects and __del__ with Boehm") static_body = '\n'.join(_static_deallocator_body_for_type('v', TYPE)) - d = {'pop_alive': LLTransformerOp(self, 'pop_alive'), + d = {'pop_alive': LLTransformerOp(self.pop_alive), 'PTR_TYPE':lltype.Ptr(TYPE), 'cast_adr_to_ptr': llmemory.cast_adr_to_ptr} src = ("def ll_finalizer(addr):\n" From ale at codespeak.net Wed May 3 18:57:57 2006 From: ale at codespeak.net (ale at codespeak.net) Date: Wed, 3 May 2006 18:57:57 +0200 (CEST) Subject: [pypy-svn] r26735 - pypy/dist/pypy/rpython/rctypes/socketmodule Message-ID: <20060503165757.4C3E210094@code0.codespeak.net> Author: ale Date: Wed May 3 18:57:56 2006 New Revision: 26735 Modified: pypy/dist/pypy/rpython/rctypes/socketmodule/ctypes_socket.py Log: A pointer to c_char_p change Modified: pypy/dist/pypy/rpython/rctypes/socketmodule/ctypes_socket.py ============================================================================== --- pypy/dist/pypy/rpython/rctypes/socketmodule/ctypes_socket.py (original) +++ pypy/dist/pypy/rpython/rctypes/socketmodule/ctypes_socket.py Wed May 3 18:57:56 2006 @@ -328,7 +328,7 @@ gethostbyname.restype = POINTER(cConfig.hostent) gethostbyaddr = socketdll.gethostbyaddr -gethostbyaddr.argtypes = [POINTER(c_char), c_int, c_int] +gethostbyaddr.argtypes = [c_char_p, c_int, c_int] gethostbyaddr.restype = POINTER(cConfig.hostent) getservbyname = socketdll.getservbyname From ale at codespeak.net Wed May 3 19:15:37 2006 From: ale at codespeak.net (ale at codespeak.net) Date: Wed, 3 May 2006 19:15:37 +0200 (CEST) Subject: [pypy-svn] r26736 - in pypy/dist/pypy/lib/pyontology: . test Message-ID: <20060503171537.F2C2010090@code0.codespeak.net> Author: ale Date: Wed May 3 19:15:37 2006 New Revision: 26736 Modified: pypy/dist/pypy/lib/pyontology/pyontology.py pypy/dist/pypy/lib/pyontology/test/test_ontology.py Log: Intermediate checkin Modified: pypy/dist/pypy/lib/pyontology/pyontology.py ============================================================================== --- pypy/dist/pypy/lib/pyontology/pyontology.py (original) +++ pypy/dist/pypy/lib/pyontology/pyontology.py Wed May 3 19:15:37 2006 @@ -19,6 +19,7 @@ Class = URIRef(u'http://www.w3.org/2002/07/owl#Class') rdf_rest = URIRef(u'http://www.w3.org/1999/02/22-rdf-syntax-ns#rest') rdf_first = URIRef(u'http://www.w3.org/1999/02/22-rdf-syntax-ns#first') +rdf_nil = URIRef(u'http://www.w3.org/1999/02/22-rdf-syntax-ns#nil') def getUriref(ns, obj): return URIRef(namespaces[ns]+'#'+obj) @@ -27,9 +28,10 @@ if type(f) == str: tmp = file(f, "r") else: - tmp = f + tmp = f.open() start = tmp.read(10) - if "" % (self.__class__, str(self.name),self.getValues()) @@ -76,10 +87,10 @@ return self.bases def getValues(self): - return self.values + return self.values.keys() def setValues(self, values): - self.values = values + self.values = dict.fromkeys(values) class List(ClassDomain): @@ -189,7 +200,7 @@ getUriref('owl', 'Class') : ClassDomain, getUriref('owl', 'ObjectProperty') : ObjectProperty, getUriref('owl', 'AllDifferent') : AllDifferent , -## getUriref('owl', 'AnnotationProperty') : AnnotationProperty, + getUriref('owl', 'AnnotationProperty') : Property, #XXX AnnotationProperty, getUriref('owl', 'DataRange') : DataRange, getUriref('owl', 'DatatypeProperty') : DatatypeProperty, ## getUriref('owl', 'DeprecatedClass') : DeprecatedClass, @@ -222,7 +233,7 @@ def add_file(self, f, format=None): if not format: format = check_format(f) - self.graph.load(f,format=format) + self.graph.load(f, format=format) def attach_fd(self): for (s, p, o) in (self.graph.triples((None,)*3)): @@ -245,17 +256,39 @@ # Set the values of the property p to o sub = self.make_var(ClassDomain, s) obj = self.make_var(Thing, o) - res = self.variables[avar].addValue(sub, obj) + propdom = self.variables[avar] + res = propdom.addValue(sub, obj) def solve(self,verbose=0): - #self.merge_constraints() rep = Repository(self.variables.keys(), self.variables, self.constraints) return Solver().solve(rep, verbose) def consistency(self, verbose=0): self.rep = Repository(self.variables.keys(), self.variables, self.constraints) self.rep.consistency(verbose) - + + def flatten_rdf_list(self, rdf_list): + res = [] + if not type(rdf_list) == list: + avar = self.make_var(List, rdf_list) + lis = list(self.graph.objects(rdf_list, rdf_first)) + if not lis: + return res + res.append(lis[0]) + lis = list(self.graph.objects(rdf_list, rdf_rest))[0] + while lis != rdf_nil: + res.append(list(self.graph.objects(lis, rdf_first))[0]) + lis = list(self.graph.objects(lis, rdf_rest))[0] + else: + # For testing + avar = self.make_var(List, BNode('anon_%r'%rdf_list)) + if type(rdf_list[0]) == list: + res = [tuple(x) for x in rdf_list] + else: + res = rdf_list + self.variables[avar].setValues(res) + return avar + def make_var(self, cls=fd, a=''): if type(a) == URIRef: if a.find('#') != -1: @@ -272,6 +305,10 @@ return var if not var in self.variables: self.variables[var] = cls(var) + elif type(self.variables[var]) in cls.__bases__: + vals = self.variables[var].getValues() + self.variables[var] = cls(var) + self.variables[var].setValues(vals) return var #---------------- Implementation ---------------- @@ -288,44 +325,38 @@ self.constraints.append(constrain) else: # var is a builtin class - svar = self.make_var(None, s) cls =builtin_voc[var] - if not (self.variables.has_key(svar) and isinstance(self.variables[svar], cls)): + if cls == List: + return + else: + svar = self.make_var(None, s) + if not (self.variables.has_key(svar) and + isinstance(self.variables[svar], cls)): svar = self.make_var(cls, s) cls = self.variables[svar] if hasattr(cls, 'constraint'): self.constraints.append(cls.constraint) def first(self, s, var): - avar = self.make_var(ClassDomain, var) - svar = self.make_var(List, s) - vals = [] - vals += self.variables[svar].getValues() - vals.insert(0, avar) - self.variables[svar].setValues(vals) + pass def rest(self, s, var): - if var == URIRef(namespaces['rdf']+'#nil'): - return - else: - avar = self.make_var(List, var) - svar = self.make_var(List, s) - vals = [] - vals += self.variables[svar].getValues() - vals.append( avar) - self.variables[svar].setValues(vals) - + pass + def onProperty(self, s, var): svar =self.make_var(Restriction, s) avar =self.make_var(Property, var) self.variables[svar].property = avar + #---Class Axioms---#000000#FFFFFF----------------------------------------------- def subClassOf(self, s, var): # s is a subclass of var means that the # class extension of s is a subset of the - # class extension of var. + # class extension of var, ie if a indiviual is in + # the extension of s it must be in the extension of + # var avar = self.make_var(None, var) svar = self.make_var(ClassDomain, s) cons = SubClassConstraint( svar, avar) @@ -349,22 +380,36 @@ pass def oneOf(self, s, var): - avar = self.make_var(List, var) + var = self.flatten_rdf_list(var) + #avar = self.make_var(List, var) svar = self.make_var(ClassDomain, s) - cons = OneofPropertyConstraint(svar, avar) - self.constraints.append(cons) + res = self.variables[var].getValues() + self.variables[svar].setValues(res) def unionOf(self,s, var): - avar = self.make_var(List, var) + var = self.flatten_rdf_list(var) + vals = self.variables[var].getValues() + + res = [] + for val in vals: + res.extend([x for x in val]) svar = self.make_var(ClassDomain, s) - cons = UnionofConstraint(svar, avar) - self.constraints.append(cons) + vals = self.variables[svar].getValues() + res.extend(vals) + self.variables[svar].setValues(res) def intersectionOf(self, s, var): - avar = self.make_var(List, var) + var = self.flatten_rdf_list(var) + vals = self.variables[var].getValues() + res = vals[0] + for l in vals[1:]: + result = [] + for v in res: + if v in l : + result.append(v) + res = result svar = self.make_var(ClassDomain, s) - cons = IntersectionofConstraint(svar, avar) - self.constraints.append(cons) + self.variables[svar].setValues(res) #---Property Axioms---#000000#FFFFFF-------------------------------------------- @@ -407,12 +452,22 @@ svar =self.make_var(Restriction, s) constrain = MaxCardinality(svar, int(var)) self.constraints.append(constrain) - + # Make a new variable that can hold the domain of possible cardinality + # values + self.variables[svar].TBox['Cardinality'] = (range( int(var)+1), 'in') +# var_name = '%s_Cardinality' % svar +# self.variables[var_name] = fd(range(int(var)+1)) + def minCardinality(self, s, var): """ Len of finite domain of the property shall be greater than or equal to var""" svar =self.make_var(Restriction, s) constrain = MinCardinality(svar, int(var)) self.constraints.append(constrain) + self.variables[svar].TBox['Cardinality'] = ( range(int(var)), 'not in') +# var_name = '%s_Cardinality' % svar +# self.variables[var_name] = fd(range(int(var))) +# constraint = Expression(var_name,' not in') +# self.constraints.append(constraint) def cardinality(self, s, var): """ Len of finite domain of the property shall be equal to var""" @@ -420,6 +475,9 @@ # Check if var is an int, else find the int buried in the structure constrain = Cardinality(svar, int(var)) self.constraints.append(constrain) + self.variables[svar].TBox['Cardinality'] = ( [int(var)], 'in') +# var_name = '%s_Cardinality' % svar +# self.variables['var_name'] = fd(int(var)) def differentFrom(self, s, var): s_var = self.make_var(Thing, s) @@ -430,7 +488,12 @@ #XXX need to change this def distinctMembers(self, s, var): s_var = self.make_var(AllDifferent, s) - var_var = self.make_var(List, var) + var_var = self.flatten_rdf_list(var) + #var_var = self.make_var(List, var) + for v in var_var: + indx = var_var.index(v) + for other in var_var[indx+1:]: + self.differentFrom(v, other) constrain = AllDifferentConstraint(s_var, var_var) self.constraints.append(constrain) @@ -478,6 +541,14 @@ def estimateCost(self, domains): return self.cost +def get_cardinality(props, cls): + if props.get(cls): + card = len(props[cls]) + elif props.get(None): + card = len(props[None]) + else: + card = 0 + return card class MaxCardinality(AbstractConstraint): """Contraint: all values must be distinct""" @@ -498,8 +569,12 @@ """narrowing algorithm for the constraint""" prop = domains[self.variable].property props = Linkeddict(domains[prop].getValues()) - cls = domains[self.variable].getValues()[0] - if len(props[cls]) > self.cardinality: + dom = domains[self.variable].getValues() + if not dom: + return 0 + cls = dom[0] + card = get_cardinality(props, cls) + if card > self.cardinality: raise ConsistencyFailure("Maxcardinality of %i exceeded by the value %i" %(self.cardinality,len(props[cls]))) else: return 1 @@ -511,7 +586,8 @@ prop = domains[self.variable].property props = Linkeddict(domains[prop].getValues()) cls = domains[self.variable].getValues()[0] - if len(props[cls]) < self.cardinality: + card = get_cardinality(props, cls) + if card < self.cardinality: raise ConsistencyFailure("MinCardinality of %i not achieved by the value %i" %(self.cardinality,len(props[cls]))) else: return 1 @@ -523,8 +599,10 @@ prop = domains[self.variable].property props = Linkeddict(domains[prop].getValues()) cls = domains[self.variable].getValues()[0] - if len(props[cls]) != self.cardinality: - raise ConsistencyFailure("Cardinality of %i exceeded by the value %i" %(self.cardinality,len(props[cls]))) + card = get_cardinality(props, cls) + if card != self.cardinality: + raise ConsistencyFailure("Cardinality of %i exceeded by the value %r for %r" % + (self.cardinality, props[cls], prop)) else: return 1 @@ -536,7 +614,7 @@ AbstractConstraint.__init__(self, [variable, cls_or_restriction]) self.object = cls_or_restriction self.variable = variable - + def estimateCost(self, domains): return self.cost @@ -550,6 +628,7 @@ vals += superdom.getValues() vals += subdom.getValues() +[self.variable] superdom.setValues(vals) + return 0 class DisjointClassConstraint(SubClassConstraint): @@ -557,8 +636,6 @@ def narrow(self, domains): subdom = domains[self.variable] superdom = domains[self.object] -## bases = get_values(superdom, domains, 'getBases') -## subdom.bases += [bas for bas in bases if bas not in subdom.bases] vals1 = superdom.getValues() vals2 = subdom.getValues() for i in vals1: @@ -573,28 +650,31 @@ class RangeConstraint(SubClassConstraint): - cost = 200 + cost = 30 def narrow(self, domains): propdom = domains[self.variable] rangedom = domains[self.object] newrange = rangedom.getValues() - range = [] + res = [] oldrange = propdom.range if oldrange: for v in oldrange: if v in newrange: - range.append(v) + res.append(v) else: - range = newrange - propdom.range = range - prop = Linkeddict(propdom.getValues()) - for pval in sum(prop.values(),[]): - if pval not in range: - raise ConsistencyFailure("Value %r not in range %r"%(pval,range)) + res = newrange + propdom.range = res + propdom.setValues([(None,i) for i in res]) + #prop = Linkeddict(propdom.getValues()) + #for pval in sum(prop.values(),[]): + # if pval not in range: + # raise ConsistencyFailure("Value %r not in range %r for Var %s"%(pval,range, self.variable)) class DomainConstraint(SubClassConstraint): + cost = 200 + def narrow(self, domains): propdom = domains[self.variable] domaindom = domains[self.object] @@ -626,13 +706,16 @@ class EquivalentPropertyConstraint(SubClassConstraint): + cost = 100 + def narrow(self, domains): subdom = domains[self.variable] superdom = domains[self.object] vals = superdom.getValues() for val in subdom.getValues(): if not val in vals: - raise ConsistencyFailure("Value not in prescribed range") + raise ConsistencyFailure("The Property %s is not equivalent to Property %s" % + (self.variable, self.object)) class TypeConstraint(SubClassConstraint): cost = 1 @@ -654,7 +737,7 @@ domain_dict = Linkeddict(domain) for cls, val in domain_dict.items(): if len(val) != 1: - raise ConsistencyFailure("Maxcardinality exceeded") + raise ConsistencyFailure("FunctionalCardinality error") else: return 0 @@ -667,7 +750,7 @@ vals = {} for cls, val in domain: if vals.has_key(val): - raise ConsistencyFailure("Maxcardinality exceeded") + raise ConsistencyFailure("InverseFunctionalCardinality error") else: vals[val] = 1 else: @@ -682,7 +765,6 @@ else: if not v in dict.__getitem__(self,k): dict.__getitem__(self,k).append(v) -## dict.__getitem__(self,k).append(v) class TransitiveConstraint(OwlConstraint): """Contraint: all values must be distinct""" @@ -710,7 +792,8 @@ class InverseofConstraint(SubClassConstraint): """Contraint: all values must be distinct""" - + cost = 200 + def narrow(self, domains): """narrowing algorithm for the constraint""" obj_domain = domains[self.object].getValues() @@ -718,10 +801,12 @@ res = [] for cls, val in obj_domain: if not (val,cls) in sub_domain: - raise ConsistencyFailure("Inverseof failed") + raise ConsistencyFailure("Inverseof failed for (%r, %r) in %r" % + (val, cls, sub_domain) ) for cls, val in sub_domain: if not (val,cls) in obj_domain: - raise ConsistencyFailure("Inverseof failed") + raise ConsistencyFailure("Inverseof failed for (%r, %r) in %r" % + (val, cls, obj_domain)) class DifferentfromConstraint(SubClassConstraint): @@ -768,6 +853,7 @@ def narrow(self, domains): """narrowing algorithm for the constraint""" + vals =[] vals += domains[self.variable].getValues() if vals == []: @@ -775,6 +861,8 @@ while True: if vals[-1] in domains.keys() and isinstance(domains[vals[-1]], List): vals = vals[:-1] + domains[vals[-1]].getValues() + if domains[vals[-1]].remove : + domains.pop(vals[-1]) else: break domains[self.variable].setValues(vals) @@ -798,11 +886,10 @@ class OneofPropertyConstraint(AbstractConstraint): - def __init__(self, variable, List): - AbstractConstraint.__init__(self, [variable, List]) + def __init__(self, variable, list_of_vals): + AbstractConstraint.__init__(self, [variable ]) self.variable = variable - self.List = List - + self.List = list_of_vals cost = 100 def estimateCost(self, domains): @@ -811,6 +898,7 @@ def narrow(self, domains): val = domains[self.List].getValues() if isinstance(domains[self.variable],Restriction): + # This should actually never happen ?? property = domains[self.variable].property cls = domains[self.variable].getValues()[0] prop = Linkeddict(domains[property].getValues()) @@ -852,7 +940,28 @@ for u in remove: intersection.remove(u) cls = domains[self.variable].setValues(intersection) - + term = {} + for l in [domains[x] for x in val]: + if hasattr(l,'TBox'): + TBox = l.TBox + prop = l.property + for item in TBox.values(): + term.setdefault(prop,[]) + term[prop].append(item) + for prop in term: + axioms = term[prop] + ranges = [ax[0] for ax in axioms] + res = [] + while axioms: + r, comp = axioms.pop(0) + if res: + res = [x for x in res if eval('x %s r' % comp)] + else: + res = [x for x in r if eval('x %s r' % comp)] + if not res: + axioms.append((r,comp)) + if not res: + raise ConsistencyFailure("Inconsistent use of intersectionOf") class SomeValueConstraint(OneofPropertyConstraint): Modified: pypy/dist/pypy/lib/pyontology/test/test_ontology.py ============================================================================== --- pypy/dist/pypy/lib/pyontology/test/test_ontology.py (original) +++ pypy/dist/pypy/lib/pyontology/test/test_ontology.py Wed May 3 19:15:37 2006 @@ -11,15 +11,17 @@ from pypy.lib.pyontology.pyontology import * # Ontology, ClassDomain, SubClassConstraint from rdflib import Graph, URIRef, BNode +UR = URIRef def rdf_list(ont, name, data): owllist = URIRef(name) obj = URIRef(namespaces['rdf']+'#List') ont.type(owllist, obj) own =owllist for i,dat in enumerate(data[:-1]): - next = URIRef( name + str(i)) + next = BNode( name + str(i)) print next,i,dat,own ont.first(own, dat) + ont.type(next, obj) ont.rest(own, next) own = next ont.first(own, data[-1]) @@ -189,7 +191,7 @@ assert len(O.constraints) == 2 for con in O.constraints: con.narrow(O.variables) - assert O.variables['a_'].getValues() ==[] #O.variables['b_'] + assert O.variables['a_'].getValues() ==[] def test_subproperty(): O = Ontology() @@ -340,6 +342,7 @@ py.test.raises(ConsistencyFailure, O.consistency) def test_List(): + py.test.skip("Need to be rewritten using RDF-XML") O = Ontology() own = URIRef('favlist') obj = URIRef(namespaces['rdf']+'#List') @@ -350,52 +353,34 @@ O.rest( URIRef('1'), URIRef('2')) O.first( URIRef('2'), 2) O.rest( URIRef('2'), URIRef(namespaces['rdf']+'#nil')) - assert len(O.constraints) == 1 + O.flatten_rdf_list(own) O.consistency(5) assert O.rep._domains['favlist_'].getValues() == [0,1,2] - -def test_oneofrestriction(): - O = Ontology() - restrict = BNode('anon') - obj = URIRef(namespaces['owl']+'#Restriction') - O.type(restrict, obj) - p = URIRef('p') - O.onProperty(restrict,p) - obj = URIRef(namespaces['owl']+'#ObjectProperty') - O.type(p, obj) - p = URIRef('favlist') - O.oneOf(restrict, p) - own = rdf_list(O, 'favlist', [0, 1, 2]) - own = URIRef('class') - obj = URIRef(namespaces['rdf']+'#Class') - O.type(own, obj) - O.subClassOf(own,restrict) - py.test.raises(ConsistencyFailure, O.consistency) def test_oneofclassenumeration(): O = Ontology() restrict = BNode('anon') - own = rdf_list(O, 'favlist', ['first', 'second', 'third']) + own = [UR('first'), UR('second'), UR('third')] O.oneOf(restrict, own) O.type(restrict, namespaces['owl']+'#Class') O.consistency(4) - print O.rep._domains assert len(O.rep._domains[restrict].getValues()) == 3 + assert set(O.rep._domains[restrict].getValues()) == set(own) def test_oneofdatarange(): O = Ontology() restrict = BNode('anon') - own = rdf_list(O, 'favlist', ['1','2','3']) + own = ['1','2','3'] O.oneOf(restrict, own) O.type(restrict, namespaces['owl']+'#DataRange') O.consistency(4) - print O.rep._domains assert len(O.rep._domains[restrict].getValues()) == 3 + assert set(O.rep._domains[restrict].getValues()) == set(own) def test_somevaluesfrom_datarange(): O = Ontology() datarange = BNode('anon') - own = rdf_list(O, 'favlist', ['1','2','3']) + own = ['1','2','3'] O.oneOf(datarange, own) O.type(datarange, namespaces['owl']+'#DataRange') restrict = BNode('anon1') @@ -416,7 +401,7 @@ def test_allvaluesfrom_datarange(): O = Ontology() datarange = BNode('anon') - own = rdf_list(O, 'favlist', ['1','2','3']) + own = ['1','2','3'] O.oneOf(datarange, own) O.type(datarange, namespaces['owl']+'#DataRange') restrict = BNode('anon1') @@ -439,27 +424,22 @@ cls = BNode('anon') own1 = BNode('liist1') own2 = BNode('liist2') - list1 = rdf_list(O, 'favlist1', ['1', '2', '3']) - list2 = rdf_list(O, 'favlist2', ['3', '4', '5']) - own = rdf_list(O, 'favlist', [own1, own2]) + list1 = ['1', '2', '3'] + list2 = ['3', '4', '5'] + own = [list1, list2] O.oneOf( own1, list1) O.oneOf( own2, list2) O.unionOf(cls, own) O.type(cls, namespaces['owl']+'#Class') O.consistency(3) - assert O.rep._domains[cls].getValues() == ['1', '2', '3', '4', '5'] + res = O.rep._domains[cls].getValues() + res.sort() + assert res == ['1', '2', '3', '4', '5'] def test_intersectionof(): O = Ontology() cls = BNode('anon') - own1 = BNode('liist1') - own2 = BNode('liist2') - list1 = rdf_list(O, 'favlist1', ['1', '2', '3']) - list2 = rdf_list(O, 'favlist2', ['3', '4', '5']) - own = rdf_list(O, 'favlist', [own1, own2]) - O.oneOf( own1, list1) - O.oneOf( own2, list2) - O.intersectionOf(cls, own) + O.intersectionOf(cls, [['1','2','3'],['3','4','5']]) O.type(cls, namespaces['owl']+'#Class') O.consistency(3) assert O.rep._domains[cls].getValues() == ['3'] @@ -502,7 +482,6 @@ O.type(sub, obj) O.variables[O.make_var(None,sub)].setValues([(cls,'1')]) O.consistency(3) -# assert len(O.rep._constraints) == 4 assert ('liist1','1') in O.rep._domains[O.make_var(None,sub)].getValues() def test_sameasconsistency(): @@ -516,8 +495,38 @@ obj = URIRef(namespaces['owl']+'#ObjectProperty') O.type(sub, obj) O.variables[O.make_var(None,sub)].setValues([(cls,'1'), (own1,'2')]) - print O.variables for dom in O.variables.values() :print type(dom) py.test.raises(ConsistencyFailure, O.consistency, 3) +def test_cardinality_terminology(): + py.test.skip("In progress") + # Modeled after one of the standard tests (approved/maxCardinality) + # 'cls' by subclassing two maxCardinality restrictions becomes the set of + # individuals satisfying both restriction, ie having exactly 2 values of + # predicate p + + O = Ontology() + cls = URIRef('cls') + O.type(cls, namespaces['owl']+'#Class') + + p = URIRef('p') + O.type(p, namespaces['owl']+'#ObjectProperty') + + restr = BNode('anon') + O.subClassOf(cls, restr) + O.maxCardinality(restr, 2) + O.type(restr, namespaces['owl']+'#Restriction') + O.onProperty(restr, p) + + restr2 = BNode('anon2') + O.type(restr2, namespaces['owl']+'#Restriction') + O.onProperty(restr2, p) + O.subClassOf(cls, restr2) + O.minCardinality(restr2, 3) + constraints = len(O.constraints) + py.test.raises(ConsistencyFailure, O.consistency, 3) + assert len(O.constraints) < constraints + py.test.raises(ConsistencyFailure, O.consistency, 3) + + From cfbolz at codespeak.net Wed May 3 19:49:11 2006 From: cfbolz at codespeak.net (cfbolz at codespeak.net) Date: Wed, 3 May 2006 19:49:11 +0200 (CEST) Subject: [pypy-svn] r26737 - in pypy/dist/pypy/module/_weakref: . test Message-ID: <20060503174911.8AA1010091@code0.codespeak.net> Author: cfbolz Date: Wed May 3 19:49:08 2006 New Revision: 26737 Modified: pypy/dist/pypy/module/_weakref/interp__weakref.py pypy/dist/pypy/module/_weakref/test/test_weakref.py Log: fix getweakrefcount: until now, a weakref without callback never went away, even if its last reference got removed, because it was cached. That is what CPython does too (and there are tests for it). The problem is that then getweakrefcount returns a wrong number of weakrefs in this case, since it cannot distinguish between a weakref which is there because it is really used and a weakref which is just cached (but not referenced from anywhere else). CPython does this by looking at the refcount. I think it is more important that getweakrefcount is correct than that caching works exactly identical to CPython. Modified: pypy/dist/pypy/module/_weakref/interp__weakref.py ============================================================================== --- pypy/dist/pypy/module/_weakref/interp__weakref.py (original) +++ pypy/dist/pypy/module/_weakref/interp__weakref.py Wed May 3 19:49:08 2006 @@ -14,8 +14,8 @@ class WeakrefLifeline(object): def __init__(self): self.addr_refs = [] - self.w_cached_weakref = None - self.w_cached_proxy = None + self.cached_weakref_index = -1 + self.cached_proxy_index = -1 def __del__(self): for i in range(len(self.addr_refs) - 1, -1, -1): @@ -33,21 +33,23 @@ w_weakreftype = space.gettypeobject(W_Weakref.typedef) is_weakreftype = space.is_w(w_weakreftype, w_subtype) can_reuse = space.is_w(w_callable, space.w_None) - if is_weakreftype and can_reuse and self.w_cached_weakref is not None: - return self.w_cached_weakref + if is_weakreftype and can_reuse and self.cached_weakref_index >= 0: + cached_weakref_address = self.addr_refs[self.cached_weakref_index] + return cast_address_to_object(cached_weakref_address, W_Weakref) w_ref = space.allocate_instance(W_Weakref, w_subtype) index = len(self.addr_refs) W_Weakref.__init__(w_ref, space, self, index, w_obj, w_callable) self.addr_refs.append(cast_object_to_address(w_ref)) if is_weakreftype and can_reuse: - self.w_cached_weakref = w_ref + self.cached_weakref_index = index return w_ref def get_proxy(self, space, w_obj, w_callable): can_reuse = space.is_w(w_callable, space.w_None) - if can_reuse and self.w_cached_proxy is not None: - return self.w_cached_proxy + if can_reuse and self.cached_proxy_index >= 0: + cached_proxy_address = self.addr_refs[self.cached_proxy_index] + return cast_address_to_object(cached_proxy_address, W_Proxy) index = len(self.addr_refs) if space.is_true(space.callable(w_obj)): w_proxy = W_CallableProxy(space, self, index, w_obj, w_callable) @@ -55,11 +57,15 @@ w_proxy = W_Proxy(space, self, index, w_obj, w_callable) self.addr_refs.append(cast_object_to_address(w_proxy)) if can_reuse: - self.w_cached_proxy = w_proxy + self.cached_proxy_index = index return w_proxy def ref_is_dead(self, index): self.addr_refs[index] = NULL + if self.cached_proxy_index == index: + self.cached_proxy_index = -1 + if self.cached_weakref_index == index: + self.cached_weakref_index = -1 class W_WeakrefBase(Wrappable): Modified: pypy/dist/pypy/module/_weakref/test/test_weakref.py ============================================================================== --- pypy/dist/pypy/module/_weakref/test/test_weakref.py (original) +++ pypy/dist/pypy/module/_weakref/test/test_weakref.py Wed May 3 19:49:08 2006 @@ -91,6 +91,19 @@ wref1 = wref(a) assert isinstance(wref1, wref) + def test_correct_weakrefcount_after_death(self): + import _weakref + class A: + pass + a = A() + ref1 = _weakref.ref(a) + ref2 = _weakref.ref(a) + assert _weakref.getweakrefcount(a) == 1 + del ref1 + assert _weakref.getweakrefcount(a) == 1 + del ref2 + assert _weakref.getweakrefcount(a) == 0 + def test_weakref_equality(self): import _weakref class A: From dialtone at codespeak.net Wed May 3 21:37:57 2006 From: dialtone at codespeak.net (dialtone at codespeak.net) Date: Wed, 3 May 2006 21:37:57 +0200 (CEST) Subject: [pypy-svn] r26738 - in pypy/dist/pypy/translator/cl: . test Message-ID: <20060503193757.86DBA10090@code0.codespeak.net> Author: dialtone Date: Wed May 3 21:37:35 2006 New Revision: 26738 Modified: pypy/dist/pypy/translator/cl/opformatter.py pypy/dist/pypy/translator/cl/test/test_dict.py Log: add stubs for DictItemsIteratorImpl, add a failing dict_iter test Modified: pypy/dist/pypy/translator/cl/opformatter.py ============================================================================== --- pypy/dist/pypy/translator/cl/opformatter.py (original) +++ pypy/dist/pypy/translator/cl/opformatter.py Wed May 3 21:37:35 2006 @@ -1,4 +1,5 @@ from pypy.rpython.ootypesystem.ootype import List, Dict, Record, Instance +from pypy.rpython.ootypesystem.ootype import DictItemsIterator from pypy.translator.cl.clrepr import clrepr class OpFormatter: @@ -117,6 +118,10 @@ impl = DictImpl(selfvar) code = getattr(impl, method)(*args) yield "(setf %s %s)" % (result, code) + elif isinstance(cls, DictItemsIterator): + impl = DictItemsIteratorImpl(selfvar) + code = getattr(impl, method)(*args) + yield "(setf %s %s)" % (result, code) elif isinstance(cls, Instance): name = clrepr(method, symbol=True) funcall = " ".join((name, selfvar) + args) @@ -193,3 +198,18 @@ def ll_set(self, key, value): return "(setf (gethash %s %s) %s)" % (key, self.obj, value) + + def ll_get_items_iterator(self): + raise NotImplementedError() + +class DictItemsIteratorImpl: + + def __init__(self, obj): + self.obj = obj + + def ll_go_next(self): + raise NotImplementedError() + + def ll_current_key(self): + raise NotImplementedError() + Modified: pypy/dist/pypy/translator/cl/test/test_dict.py ============================================================================== --- pypy/dist/pypy/translator/cl/test/test_dict.py (original) +++ pypy/dist/pypy/translator/cl/test/test_dict.py Wed May 3 21:37:35 2006 @@ -13,3 +13,14 @@ return dic[number] cl_dict_get = make_cl_func(dict_get, [int]) assert cl_dict_get(42) == 43 + +def test_dict_iter(): + py.test.skip("not supported yet") + def dict_iter(): + dic = {1:2, 3:4, 5:6} + i = 0 + for key in dic: + i = i + dic[key] + return i + cl_dict_iter = make_cl_func(dict_iter, []) + assert cl_dict_iter() == 12 \ No newline at end of file From bea at codespeak.net Wed May 3 23:07:44 2006 From: bea at codespeak.net (bea at codespeak.net) Date: Wed, 3 May 2006 23:07:44 +0200 (CEST) Subject: [pypy-svn] r26739 - pypy/extradoc/talk/agile2006 Message-ID: <20060503210744.DCEA610091@code0.codespeak.net> Author: bea Date: Wed May 3 23:07:36 2006 New Revision: 26739 Modified: pypy/extradoc/talk/agile2006/draftpaper_agile2006.txt Log: tuning, tuning and more tuning - please review.... Modified: pypy/extradoc/talk/agile2006/draftpaper_agile2006.txt ============================================================================== --- pypy/extradoc/talk/agile2006/draftpaper_agile2006.txt (original) +++ pypy/extradoc/talk/agile2006/draftpaper_agile2006.txt Wed May 3 23:07:36 2006 @@ -10,7 +10,7 @@ PyPy is an Open Source project, partly funded by the European Union, employing agile techniques evolved within the Python Community such as "sprint-driven development".The project started as a grass-root F/OSS effort in late 2002 and -recieved EU-funding from December 2004 until November 2006. In this paper we +received EU-funding from December 2004 until November 2006. In this paper we will present the various influencing factors that creates the hybrid project process that is PyPy. These influencing factors are the F/OSS Python Community (climate of the community from which PyPy grew from), agile practices (such as @@ -19,7 +19,7 @@ influencing factors laid the foundation for the custom-made project process that makes this unique hybrid project work and the main factor for driving this process is the skills of the team of core developers instigating the project. -PyPy, with it?s open and transparent communication and collaborative workstyle, +PyPy, with its open and transparent communication and collaborative work style, is again a proof that the best agile practice is the people factor. .. raw:: latex @@ -32,8 +32,8 @@ ============= This paper presents the story and the experiences gathered so far in the PyPy -project concerning how to integrate such diverse perspectives as agile -practices being used in a distributed and dispersed development style in an +project. The challenge has been to integrate such diverse perspectives as agile +practices being used in a distributed development style in an Open Source project that is partly funded by the European Union. The PyPy project started as a grass-root effort among core developers in the @@ -42,7 +42,7 @@ driven from a non-profit perspective which rapidly increased in complexity when the Open Source project applied for EU-funding. -Today the project have over 4 years of intense activity as a Open Source +Today the project has over 4 years of intense activity as an Open Source community (F/OSS) effort and have completed a successful first year of the EU-funded effort. In order to understand how the PyPy project managed and manages to strike a balance between being an F/OSS community, while also having @@ -53,9 +53,9 @@ The influencing factors of the PyPy project process are: - The F/OSS/Python community factor. Different Open Source communities have - different "flavours" regarding culture, communication climate, structure, + different "flavors" regarding culture, communication climate, structure, decision-process etc. PyPy was born out of the Python Community and share - some of it?s characteristics which have had a huge influence on the project + some of its characteristics which have had a huge influence on the project process so far. Aspects such as distributed/dispersed development and the supporting practices and infrastructure in place to quality assure software development in a collaborated manner are part of this important influencing @@ -73,14 +73,14 @@ Driven Development and explain how these are implemented in PyPy. - The EU factor. PyPy is the first F/OSS community that organized themselves - into an EU-project, recieving EU-funding. It has had a huge impact on the + into an EU-project, receiving EU-funding. It has had a huge impact on the project, and it is important to identify how EU project and process requirements can be "weaved" into an Agile F/OSS project - a challenge - indeed. The EU-funding has been and still is an enourmous opportunity, the + indeed. The EU-funding has been and still is an enormous opportunity, the project would not have had the rapid progress and impact it is now having without the funding. It is also very important to note that without striking the right balance between the three main influencing factors (F/OSS, agile - and EU-funding) this factor might also prove to be a "showstopper", something + and EU-funding) this factor might also prove to be a "show stopper", something that might influence the PyPy community negatively. This is a constant challenge - we explain here how we created our process and added a "consortium-level" structure to the F/OSS community and the steps we took in @@ -88,7 +88,7 @@ Our conclusion so far in the project is that we believe that the practice of "sprinting", as being used in the PyPy project, makes Agile and -Distributed/dispersed workstyles more possible to combine. We also believe it + Distributed/dispersed work styles more possible to combine. We also believe it is a very useful practice for creating value and ensuring quality in a projects with hybrid cultures and methodologies. It is our aim to start to show-case this with experiences from the first funded year of PyPy. We also feel that our @@ -126,7 +126,7 @@ optimized compiler and interpreter purely in Python, applying Aspect Oriented Programming and abstract interpretation techniques. The methodology objective aims at showcasing the "sprint-driven development method" being used by PyPy -and you can view this paper as part of fullfilling the methodology objective. +and you can view this paper as part of fulfilling the methodology objective. Strategy: +++++++++ @@ -150,8 +150,8 @@ It is difficult to estimate the amount of people involved in PyPy but we estimate that ca 300-500 people "follow actively" the progress of the project - -this might mean reading emails, IRC logs and documention in some cases, asking -questions and sending bug reports in other cases.There are ca 50 people that +this might mean reading emails, IRC logs and documentation in some cases, asking +questions and sending bug reports in other cases. There are ca 50 people that have commit-rights to the source code. The core group of developers consists of ca 10 people. @@ -166,14 +166,14 @@ work-packages and in total 58 deliverables which are high-level functional and non-functional requirements that were formulated in a proposal and form the "Description of Work" in the contract with the European Commission. The funding -recieved for this effort is 1.3 million euros. Of the core group of developers +received for this effort is 1.3 million euro. Of the core group of developers mentioned above almost all of them (ca 10 people) are involved in some sense in the partner companies and organizations of the PyPy consortium. History: ++++++++ -The ideas behind PyPy started via discussions on european mailing-lists in the +The ideas behind PyPy started via discussions on European mailing-lists in the Python community late 2002 by people that had been active in the Python community for some time, core developers interested in language implementation. They based the discussions and ideas partly on their experiences with @@ -234,14 +234,14 @@ previous successful Python projects and this prior community experience was vital for the evolving of the PyPy community due to the established trust in expert skills of the core developers starting PyPy - again the people -factor.Thus making it easier recruit people into the PyPy community. +factor. Thus making it easier recruit people into the PyPy community. The PyPy project inherited the focus on collaborative approaches and open communication climate. The nature of using sprints as a core technique as a way to kick-start the project as well as moving the sprints to different locations as a strategy to encourage participation by meeting people locally are clear examples of this. During the period of 2003-2004 6 sprints were -arranged in various european cities, hosted by universities and private +arranged in various European cities, hosted by universities and private persons, participation funded privately. The effect on the evolving community was a stable subscriber participation on the development list of between 140-150 people. After the EU-funding and the more systematic structure of @@ -274,11 +274,11 @@ The main communication channels between developers involved in PyPy is to discuss over IRC (Internet-Relay-Chat) - open for all that are interested. -Several mailinglists for discussions and information is also used. Webpages, +Several mailing lists for discussions and information is also used. Web pages, documentation, tutorials, talks and papers etc are all available on the central -developer server for everyone.A very useful feature that really supports +developer server for everyone to access. A very useful feature that really supports information and communication (the author can attest to this from her own -experience) are the public email archives covering the key mailinglists - going +experience) are the public email archives covering the key mailing lists - going back to the start of 2003. An extensive coding guide, published on codespeak.net (development website) @@ -287,9 +287,9 @@ test and documentation guidelines. Now - all this infrastructure is being used in almost all larger open source -projects and quite a few of them are much more hierarchial and non-transparent -in their communication. In PyPy there is no hierarchy for recieving -commit-rights. A newcomer to PyPy can instantly recieve an account on the +projects and quite a few of them are much more hierarchical and non-transparent +in their communication. In PyPy there is no hierarchy for receiving +commit-rights. A newcomer to PyPy can instantly receive an account on the development server, with full commit rights to the version control system. The reason why there are no constraints is that the process is very much self-organized and managed by the developers from a social level (peer review, @@ -297,7 +297,7 @@ strong automated tools covering tests, versions and back ups covering the technical level. -In a distributed and dispersed workstyle these two (social and technical) +In a distributed and dispersed work style these two (social and technical) levels needs to be consistent and support each other, discrepancies would be immediately noticed. As stated before - the people factor is again evident and in order to encourage participation and contribution there has to be trust as @@ -316,15 +316,15 @@ Sync-meetings are weekly short coordination meetings between developers, open to all developers active in the PyPy community, usually but not necessarily involving aspects of EU-funded work on deliverables. These 30 minute -IRC-meetings serve a weekly synchronisation for regular discussions and +IRC-meetings serve a weekly synchronization for regular discussions and integration of ongoing work. Meetings are prepared with an agenda sent out to pypy-dev and minutes are distributed on pypy-dev and archived in the repository -with publicly accessible links.Preparing, managing and documenting the meetings +with publicly accessible links. Preparing, managing and documenting the meetings is rotated between active developers and is self-organized as well. -Sync-meetings have proven to be a very good complement to a process in which +Sync-meetings have proved to be a very good complement to a process in which the project sprints every 6th week. Sync-meetings keep cohesion as well as a -team focus-and-feel for the dispersed workstyle between sprints. +team focus-and-feel for the dispersed work style between sprints. Influencing factors: agile practices in PyPy ============================================ @@ -349,7 +349,7 @@ community (framework-centric, distributed, no "business user" present), some of the XP mantras /practices couldn't be done directly. We decided to try to do "as much XP as possible" for short, highly-focused sessions, with all active -committers colocated." +committers collocated." The Zope community as well as other Python projects such as PyPy have seen that sprints have goals beyond the creation of software: @@ -358,7 +358,7 @@ with the core developers. - It is a live training session not only in producing code but also in the - development methods being used (TDD, pairprogramming etc, the sprint method + development methods being used (TDD, pair programming etc, the sprint method in itself). - It supports activities such as design decisions and high-level requirements @@ -384,7 +384,7 @@ sprint driven development. The sprint method, as well as key aspects of F/OSS supportive infrastructure -and practices was established within the project before PyPy recieved it?s +and practices was established within the project before PyPy received it?s EU-funding. Thus, in the proposal,we put much emphasis on the methodology in itself when designing the consortium level process. Examples of how this was done was that we created a methodology objective, specific deliverables @@ -401,11 +401,11 @@ Why did PyPy choose sprinting as a key technique? It is a method that fits distributed teams well because it gets the team focused around visible -challenging goals while working collarobatively (pair-programming, status +challenging goals while working collaboratively (pair-programming, status meetings, discussions etc) as well as accelerated (short increments and tasks, "doing" and testing instead of long startups of planning and requirement gathering, continuous integration). This means that most of the time a sprint -is a great way of getting results and getting new people aquainted - a good +is a great way of getting results and getting new people acquainted - a good method for dissemination of knowledge and learning within the team. A key insight, worthwhile for other EU-projects to ponder, is how an agile @@ -426,11 +426,11 @@ - a consortium of partners performing the work described in the contract -- a project co-ordinator managing contract administration and communication +- a project co-coordinator managing contract administration and communication between consortium and the Commission - a project manager, responsible for the project reaching it?s goals within the - timeframe and budget + time frame and budget The challenge was to design a project process that created a minimal amount of changes to the structure being in use in the F/OSS project. It was especially @@ -440,7 +440,7 @@ the project. We identified a minimalistic approach of management roles (project -co-ordinator, project manager, assistant project manager) and created a +co-coordinator, project manager, assistant project manager) and created a management team to make sure that there was collaboration between these roles. Although the responsibility rested on the different management roles and the management team the strategy implemented was to delegate as much as possible of @@ -460,10 +460,10 @@ play. Sprints were budgeted for and designed into the process, together with a -timeplan for all deliverables. The project was divided into three different -phases, depending on the nature of the workflow. In that sense you could +time plan for all deliverables. The project was divided into three different +phases, depending on the nature of the work flow. In that sense you could describe the EU-part of the project as a fixed-contract style of work, but with -timeplan, deliverables and work package descriptions on a high-level, not +time plan, deliverables and work package descriptions on a high-level, not broken down into more granular tasks. Resource tracking and reporting @@ -471,24 +471,24 @@ The nature of reporting on a consortium level is very much focused on the costs incurred by each partner compared to budget, by the consortium on a specific -workpackage and of the consortium overall. The consortium is free to reallocate -budgeted manmonth funding between partners during the project. The project +work package and of the consortium overall. The consortium is free to reallocate +budgeted man month funding between partners during the project. The project reports costs per period - PyPy have two periods. Again - the need for open and transparent communication together with a collaborative climate created the need to have what we believe a unique view on -cost reporting within the project. In PyPy all timesheets are gathered on a +cost reporting within the project. In PyPy all time sheets are gathered on a monthly basis and stored in central repository, accessible for all consortium partners (managers and developers alike). Cost claims from all partners are gathered on a six month basis. This data helps the management board and technical board to assess the status of work. -Templates for timesheets, costs claims, resource tracking tools etc are created +Templates for time sheets, costs claims, resource tracking tools etc are created in open formats and all data is stored under the same version control that we use for the source code. All reports are produced with docutils/ReST format -which together with automated mailinglists for covering updates in the version +which together with automated mailing lists for covering updates in the version control repositories allows for collaborate peer-reviewing regarding the -EU-level of reports. Again the strategy was to use the same tools and practises +EU-level of reports. Again the strategy was to use the same tools and practices on consortium level work as is used in the development process. Interesting to note is that the technical reports written for the Commission regarding certain deliverables and progress have also been a great help towards the community who @@ -507,13 +507,13 @@ The communication infrastructure being used on the consortium level of work mirrors that of the development work - having years of experience on the -distributed workstyle. In the case of PyPY there are mailinglists as well as +distributed work style. In the case of PyPY there are mailing lists as well as IRC channels for consortium level work. We even implemented a procedure in our internal consortium agreement to allow for virtual meetings for decisions in the consortium. So far this have been the primary meeting form and it has worked well as a channel for making decisions. IRC-logs and minutes support the procedure. In some cases decisions have also been made via email on the -consortium mailinglist. +consortium mailing list. Although not the primary focus it is also useful to have the regular sprints to coordinate specific issues between some partners or between all partners, have @@ -521,7 +521,7 @@ board etc. Our funding have also resulted in the possibility to have a more unorthodox -documention - the project have experimented in filming sprints to show the +documentation - the project have experimented in filming sprints to show the development method as well as filming talks and discussion. Our film material is planned to be released before summer 2006. @@ -531,7 +531,7 @@ Developer driven versus formal project structure ------------------------------------------------ -The fear of a top-down, hierarchial decision process of the consortium was a +The fear of a top-down, hierarchical decision process of the consortium was a justified one. It is interesting for us to note that now, having the experience and more contractual overview to note that there is nothing in the requirements from the Commission that forces a project to a more traditional @@ -542,7 +542,7 @@ as consortium work. The majority of the partners on key roles in the consortium organization had -been working together since before the funding, procedures and best practises +been working together since before the funding, procedures and best practices had been tried out. The results from the first year showed that a minimalistic path could be identified and that the important work would be to review and adjust the process when it did not support the work any more, or new situations @@ -555,7 +555,7 @@ Agile strategies versus formal EU-contractual requirements ---------------------------------------------------------- -Our main agile practise, sprint-driven development, was successfully integrated +Our main agile practice, sprint-driven development, was successfully integrated into the formal contractual requirements, allowing for the same free-floating agile process of self organizing and decision making as existed before the funding, but with a more systematic and documented style. @@ -566,7 +566,7 @@ "open-door" policy that allowed us to fund non-consortium persons from the community to attend sprints. The budget was allocated, the procedure within the sprint context of handling more newcomers were known to us - the main -showstopper was that PyPy sprint funding did not fit within the customs and +show stopper was that PyPy sprint funding did not fit within the customs and practices of contracts for cost claims in the Commission. Every time we want to encourage participation and fund people to participate in @@ -603,7 +603,7 @@ is progressing much more rapidly in PyPy than more normal F/OSS projects. The speed and the dramatically increasing learning curve could make members more passive because they do not have the time to follow full-time IRC discussions, -postings on mailinglists and the actual source code and increasing test suites. +postings on mailing lists and the actual source code and increasing test suites. This is a challenge and it is the focus of the developer group to try to distill and package information in order to help people to better navigate the @@ -620,7 +620,7 @@ We believe so. The one clear dominating factor to make all this succeed is, as always, the people factor, the CRACK performers as Boehm and Turner calls them ("Collaborative, Representative, Authorized, Committed, Knowledgeable"). -. + The core developers of the PyPy project had the right mix of various skills in order to succeed in setting up a hybrid environment - enabling them to work @@ -650,9 +650,8 @@ Drawing from these different skills within the community of developers in the PyPy project one possible conclusion would be that a truly agile approach -dominating the workstyle of an Open Source project will increase the ability of +dominating the work style of an Open Source project will increase the ability of the community to spread the strategy of agility to other domains such as entrepreneurship and business models (whether this is done by separate individuals, subgroups or the whole group). By doing this hybrid projects such as PyPy and others (Zope Europe among others) are made possible. - From cfbolz at codespeak.net Wed May 3 23:18:44 2006 From: cfbolz at codespeak.net (cfbolz at codespeak.net) Date: Wed, 3 May 2006 23:18:44 +0200 (CEST) Subject: [pypy-svn] r26740 - pypy/extradoc/talk/agile2006 Message-ID: <20060503211844.07C981009C@code0.codespeak.net> Author: cfbolz Date: Wed May 3 23:18:37 2006 New Revision: 26740 Modified: pypy/extradoc/talk/agile2006/draftpaper_agile2006.pdf pypy/extradoc/talk/agile2006/draftpaper_agile2006.txt Log: make the text valid ReST. regenerated pdf. still without the diagram, though Modified: pypy/extradoc/talk/agile2006/draftpaper_agile2006.pdf ============================================================================== Binary files. No diff available. Modified: pypy/extradoc/talk/agile2006/draftpaper_agile2006.txt ============================================================================== --- pypy/extradoc/talk/agile2006/draftpaper_agile2006.txt (original) +++ pypy/extradoc/talk/agile2006/draftpaper_agile2006.txt Wed May 3 23:18:37 2006 @@ -88,7 +88,7 @@ Our conclusion so far in the project is that we believe that the practice of "sprinting", as being used in the PyPy project, makes Agile and - Distributed/dispersed work styles more possible to combine. We also believe it +Distributed/dispersed work styles more possible to combine. We also believe it is a very useful practice for creating value and ensuring quality in a projects with hybrid cultures and methodologies. It is our aim to start to show-case this with experiences from the first funded year of PyPy. We also feel that our From sanxiyn at codespeak.net Thu May 4 06:36:57 2006 From: sanxiyn at codespeak.net (sanxiyn at codespeak.net) Date: Thu, 4 May 2006 06:36:57 +0200 (CEST) Subject: [pypy-svn] r26746 - pypy/dist/pypy/translator/cl/test Message-ID: <20060504043657.7AE4F10092@code0.codespeak.net> Author: sanxiyn Date: Thu May 4 06:36:52 2006 New Revision: 26746 Modified: pypy/dist/pypy/translator/cl/test/test_dict.py Log: Fix test Modified: pypy/dist/pypy/translator/cl/test/test_dict.py ============================================================================== --- pypy/dist/pypy/translator/cl/test/test_dict.py (original) +++ pypy/dist/pypy/translator/cl/test/test_dict.py Thu May 4 06:36:52 2006 @@ -1,3 +1,4 @@ +import py from pypy.translator.cl.buildcl import make_cl_func def test_dict_length(): @@ -23,4 +24,4 @@ i = i + dic[key] return i cl_dict_iter = make_cl_func(dict_iter, []) - assert cl_dict_iter() == 12 \ No newline at end of file + assert cl_dict_iter() == 12 From sanxiyn at codespeak.net Thu May 4 07:17:37 2006 From: sanxiyn at codespeak.net (sanxiyn at codespeak.net) Date: Thu, 4 May 2006 07:17:37 +0200 (CEST) Subject: [pypy-svn] r26747 - in pypy/dist/pypy/translator/cl: . test Message-ID: <20060504051737.ED9CB10092@code0.codespeak.net> Author: sanxiyn Date: Thu May 4 07:17:32 2006 New Revision: 26747 Modified: pypy/dist/pypy/translator/cl/opformatter.py pypy/dist/pypy/translator/cl/test/test_dict.py Log: Pass dict_iter test, in a wrong way Modified: pypy/dist/pypy/translator/cl/opformatter.py ============================================================================== --- pypy/dist/pypy/translator/cl/opformatter.py (original) +++ pypy/dist/pypy/translator/cl/opformatter.py Thu May 4 07:17:32 2006 @@ -200,7 +200,13 @@ return "(setf (gethash %s %s) %s)" % (key, self.obj, value) def ll_get_items_iterator(self): - raise NotImplementedError() + # This is explicitly unspecified by the specification. + # Should think of a better way to do this. + return """\ +(let ((temp (gensym))) + (setf (symbol-value temp) + (with-hash-table-iterator (iter %s) + (lambda () (iter)))) temp)""" % (self.obj,) class DictItemsIteratorImpl: @@ -208,8 +214,12 @@ self.obj = obj def ll_go_next(self): - raise NotImplementedError() + return """\ +(multiple-value-bind (more key value) + (funcall (symbol-value %s)) + (setf (get %s 'key) key) + (setf (get %s 'value) value) + more)""" % (self.obj, self.obj, self.obj) def ll_current_key(self): - raise NotImplementedError() - + return "(get %s 'key)" % (self.obj,) Modified: pypy/dist/pypy/translator/cl/test/test_dict.py ============================================================================== --- pypy/dist/pypy/translator/cl/test/test_dict.py (original) +++ pypy/dist/pypy/translator/cl/test/test_dict.py Thu May 4 07:17:32 2006 @@ -16,7 +16,6 @@ assert cl_dict_get(42) == 43 def test_dict_iter(): - py.test.skip("not supported yet") def dict_iter(): dic = {1:2, 3:4, 5:6} i = 0 From ale at codespeak.net Thu May 4 10:38:57 2006 From: ale at codespeak.net (ale at codespeak.net) Date: Thu, 4 May 2006 10:38:57 +0200 (CEST) Subject: [pypy-svn] r26752 - pypy/dist/pypy/module/_socket Message-ID: <20060504083857.9421A10090@code0.codespeak.net> Author: ale Date: Thu May 4 10:38:55 2006 New Revision: 26752 Modified: pypy/dist/pypy/module/_socket/interp_socket.py Log: Fixing a test failure. Apparently you cannot ask if a ctypes pointer is None, but bool(NullPointer) returns false Modified: pypy/dist/pypy/module/_socket/interp_socket.py ============================================================================== --- pypy/dist/pypy/module/_socket/interp_socket.py (original) +++ pypy/dist/pypy/module/_socket/interp_socket.py Thu May 4 10:38:55 2006 @@ -194,7 +194,7 @@ h_addr_list = ctypes.cast(hostent.contents.h_addr_list, ctypes.POINTER(ctypes.POINTER(_c.in_addr))) i = 0 addr = h_addr_list[0] - while addr is not None: + while addr: address_list.append(space.wrap(_c.inet_ntoa(addr.contents))) i += 1 addr = h_addr_list[i] From bea at codespeak.net Thu May 4 11:23:48 2006 From: bea at codespeak.net (bea at codespeak.net) Date: Thu, 4 May 2006 11:23:48 +0200 (CEST) Subject: [pypy-svn] r26753 - pypy/extradoc/sprintinfo/tokyo Message-ID: <20060504092348.1035910092@code0.codespeak.net> Author: bea Date: Thu May 4 11:23:45 2006 New Revision: 26753 Added: pypy/extradoc/sprintinfo/tokyo/sprint-report.txt Log: needs a summary of the working days - Nik, Samuele, Arre and the rest - please fill in.. Added: pypy/extradoc/sprintinfo/tokyo/sprint-report.txt ============================================================================== --- (empty file) +++ pypy/extradoc/sprintinfo/tokyo/sprint-report.txt Thu May 4 11:23:45 2006 @@ -0,0 +1,82 @@ +Tokyo 2006 Sprint Report +============================= + +Parts of the PyPy team visited Tokyo and hosted a sprint between 23-29th of April, 2006. +We sprinted in the facilities of the National Institute of Advanced Science and +Technology, being invited by The Free Software Initiative of Japan. The idea was to +promote Python as a programming language and present PyPy for Japanese hackers. + +Here is the list of people participating in the sprint: + + * Anders Lehmann + * Nik Haldimann + * Samuele Pedronis + * Beatrice D?ring + * Anders Chrigstrom (Arre) + * Eric Van Riet Paap + * Valentino Volonghi + * Sanghyeon Seo + * Yutaka Niibe + * Yusei Tahara + * George Toshida + * Koichi Sasada + +The announced goals for the sprint were: + - Work on gensqueak (our Squeak backend) or possibly other backends. + + - Implementing Python 2.5 features in PyPy. + + - Progress further on an 'rctypes' module aiming at letting us use a ctypes + implementation of an extension module from the compiled pypy-c. + + - Writing ctypes implementations of modules to be used by the above + tool. + + - Experimenting and improving performance of our garbage collectors. + + - Experiment with PyPy flexibility or other aspects of the implementation. + + - Possibly experiment with writing modules translatable for use both + in PyPy and CPython. + + - Whatever participants want to do with PyPy or particular areas + of PyPy (please send suggestions to the mailing list before to allow us to plan + and give feedback) + +After an initial round of checking general interests in the group during the first day we ended +up with this list - the content of the sprint is a mix between these goald and interests +and of course all topics on these lists were not achieved although we were productive ;-): + + - gensqueak/ootypesystem + + - Implementing Python 2.5 features in PyPy. + + - Progress further on an 'rctypes' module aiming at letting us use a ctypes + implementation of an extension module from the compiled pypy-c. + + - check status + - ctypes time and socket (and select ;)) + + - rctypes support for LLVM (Eric) + + - convert JS backend to ootypesystem + + - genjs test failure fixes + + - raisingops transformation + + - PyPy debian packaging? + + - Fun with the Common Lisp backend + + - Possibly experiment with writing modules translatable for use both + in PyPy and CPython. + +Day 1-3 +----------- + +Breakday +----------- + +Day 5-7 +---------- \ No newline at end of file From arigo at codespeak.net Thu May 4 11:36:45 2006 From: arigo at codespeak.net (arigo at codespeak.net) Date: Thu, 4 May 2006 11:36:45 +0200 (CEST) Subject: [pypy-svn] r26754 - in pypy/dist/pypy: annotation annotation/test objspace/std Message-ID: <20060504093645.5E70310095@code0.codespeak.net> Author: arigo Date: Thu May 4 11:36:43 2006 New Revision: 26754 Modified: pypy/dist/pypy/annotation/bookkeeper.py pypy/dist/pypy/annotation/builtin.py pypy/dist/pypy/annotation/test/test_annrpython.py pypy/dist/pypy/objspace/std/objspace.py Log: (pedronis, arigo) Push and pull to make space.wrap(r_uint(..)) annotate. Modified: pypy/dist/pypy/annotation/bookkeeper.py ============================================================================== --- pypy/dist/pypy/annotation/bookkeeper.py (original) +++ pypy/dist/pypy/annotation/bookkeeper.py Thu May 4 11:36:43 2006 @@ -18,6 +18,7 @@ from pypy.annotation import description from pypy.interpreter.argument import Arguments, ArgErr from pypy.rpython.rarithmetic import r_int, r_uint, r_ulonglong, r_longlong +from pypy.rpython.rarithmetic import base_int from pypy.rpython.objectmodel import r_dict, Symbolic from pypy.tool.algo.unionfind import UnionFind from pypy.rpython.lltypesystem import lltype, llmemory @@ -500,7 +501,7 @@ return SomeInteger() elif t is r_uint: return SomeInteger(nonneg = True, unsigned = True) - elif t is r_ulonglong: + elif t is r_ulonglong or t is base_int: return SomeInteger(nonneg = True, unsigned = True, size = 2) elif t is r_longlong: return SomeInteger(size = 2) Modified: pypy/dist/pypy/annotation/builtin.py ============================================================================== --- pypy/dist/pypy/annotation/builtin.py (original) +++ pypy/dist/pypy/annotation/builtin.py Thu May 4 11:36:43 2006 @@ -93,6 +93,10 @@ return constpropagate(pypy.rpython.rarithmetic.r_ulonglong, [s_obj], SomeInteger(size=2, nonneg=True, unsigned=True)) +def restricted_base_int(s_obj): + # insane hack: only for isinstance(., base_int), not for base_int() + raise Exception("cannot call rarithmetic.base_int()") + def builtin_float(s_obj): return constpropagate(float, [s_obj], SomeFloat()) @@ -140,10 +144,7 @@ if s_type.is_constant(): typ = s_type.const if issubclass(typ, pypy.rpython.rarithmetic.base_int): - if s_obj.is_constant(): - r.const = isinstance(s_obj.const, typ) - else: - r.const = issubclass(s_obj.knowntype, typ) + r.const = issubclass(s_obj.knowntype, typ) else: if typ == long: getbookkeeper().warning("isinstance(., long) is not RPython") @@ -358,6 +359,7 @@ BUILTIN_ANALYZERS[pypy.rpython.rarithmetic.r_uint] = restricted_uint BUILTIN_ANALYZERS[pypy.rpython.rarithmetic.r_longlong] = restricted_longlong BUILTIN_ANALYZERS[pypy.rpython.rarithmetic.r_ulonglong] = restricted_ulonglong +BUILTIN_ANALYZERS[pypy.rpython.rarithmetic.base_int] = restricted_base_int ##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 Modified: pypy/dist/pypy/annotation/test/test_annrpython.py ============================================================================== --- pypy/dist/pypy/annotation/test/test_annrpython.py (original) +++ pypy/dist/pypy/annotation/test/test_annrpython.py Thu May 4 11:36:43 2006 @@ -10,7 +10,7 @@ from pypy.annotation.listdef import ListDef from pypy.annotation.dictdef import DictDef from pypy.objspace.flow.model import * -from pypy.rpython.rarithmetic import r_uint +from pypy.rpython.rarithmetic import r_uint, base_int from pypy.rpython import objectmodel from pypy.objspace.flow import FlowObjSpace @@ -954,6 +954,16 @@ s = a.build_types(g, []) assert s.const == True + def test_isinstance_base_int(self): + def f(x): + return isinstance(x, base_int) + def g(n): + v = r_uint(n) + return f(v) + a = self.RPythonAnnotator() + s = a.build_types(g, [int]) + assert s.const == True + def test_alloc_like(self): class C1(object): pass Modified: pypy/dist/pypy/objspace/std/objspace.py ============================================================================== --- pypy/dist/pypy/objspace/std/objspace.py (original) +++ pypy/dist/pypy/objspace/std/objspace.py Thu May 4 11:36:43 2006 @@ -12,7 +12,7 @@ from pypy.objspace.std.multimethod import FailedToImplement from pypy.objspace.descroperation import DescrOperation from pypy.objspace.std import stdtypedef -from pypy.rpython.rarithmetic import r_longlong +from pypy.rpython.rarithmetic import base_int import sys import os import __builtin__ @@ -281,9 +281,12 @@ w_result = x.__spacebind__(self) #print 'wrapping', x, '->', w_result return w_result - if isinstance(x, r_longlong): + if isinstance(x, base_int): from pypy.objspace.std.longobject import args_from_long return W_LongObject(self, *args_from_long(x)) + + # _____ below here is where the annotator should not get _____ + if isinstance(x, long): from pypy.objspace.std.longobject import args_from_long return W_LongObject(self, *args_from_long(x)) @@ -309,7 +312,9 @@ return self.w_Ellipsis if self.options.nofaking: - # annotation should actually not get here + # annotation should actually not get here. If it does, you get + # an error during rtyping because '%r' is not supported. It tells + # you that there was a space.wrap() on a strange object. raise OperationError(self.w_RuntimeError, self.wrap("nofaking enabled: refusing " "to wrap cpython value %r" %(x,))) From bea at codespeak.net Thu May 4 12:19:33 2006 From: bea at codespeak.net (bea at codespeak.net) Date: Thu, 4 May 2006 12:19:33 +0200 (CEST) Subject: [pypy-svn] r26756 - pypy/extradoc/talk/agile2006 Message-ID: <20060504101933.A1E0E10095@code0.codespeak.net> Author: bea Date: Thu May 4 12:19:24 2006 New Revision: 26756 Modified: pypy/extradoc/talk/agile2006/draftpaper_agile2006.txt Log: language review Modified: pypy/extradoc/talk/agile2006/draftpaper_agile2006.txt ============================================================================== --- pypy/extradoc/talk/agile2006/draftpaper_agile2006.txt (original) +++ pypy/extradoc/talk/agile2006/draftpaper_agile2006.txt Thu May 4 12:19:24 2006 @@ -64,9 +64,9 @@ - The Agile factor. Almost a subset of the F/OSS/Python community factor - agile practices that has been in use since the inception of the project, that in fact have been the main drivers of the project are very much inspired by - other projects in the Python community. A key factor in this influencing + other projects in the Python community. A key aspect of this influencing factor is the Python version of "sprinting". We will present this "agile" - practice, explain and trace it?s origins within the Python community and + practice, explain and trace its origins within the Python community and identify which of the main agile practices inspired the Python world to go "sprinting" - a key technique today not only for the PyPy project but also for all main Python projects. We will also touch on aspects such as Test @@ -76,7 +76,7 @@ into an EU-project, receiving EU-funding. It has had a huge impact on the project, and it is important to identify how EU project and process requirements can be "weaved" into an Agile F/OSS project - a challenge - indeed. The EU-funding has been and still is an enormous opportunity, the + indeed. The EU-funding has been and still is an enormous opportunity; the project would not have had the rapid progress and impact it is now having without the funding. It is also very important to note that without striking the right balance between the three main influencing factors (F/OSS, agile @@ -88,8 +88,8 @@ Our conclusion so far in the project is that we believe that the practice of "sprinting", as being used in the PyPy project, makes Agile and -Distributed/dispersed work styles more possible to combine. We also believe it -is a very useful practice for creating value and ensuring quality in a projects + Distributed/dispersed work styles more possible to combine. We also believe it +is a very useful practice for creating value and ensuring quality in projects with hybrid cultures and methodologies. It is our aim to start to show-case this with experiences from the first funded year of PyPy. We also feel that our experiences as a unique hybrid project would be of interest to other @@ -105,21 +105,21 @@ Due to the dual nature of the project even such a thing as objectives can get complicated. If you, as a potential PyPy user, would visit out main developer -server codespeak you would find the following statement: +server, Codespeak, you would find the following statement: "The PyPy project aims at producing a flexible and fast Python implementation. The guiding idea is to translate a Python-level description of the Python language itself to lower level languages. Rumors have it that the secret goal is being faster-than-C which is nonsense, isn't it? more..." -Codespeak housed the F/OSS project since it?s inception and it has been a +Codespeak housed the F/OSS project since its inception and it has been a driving strategy to continue a look-and-feel of a purely F/OSS project in order to not confuse developers interested in just that - PyPy as a Python implementation. Digging a bit deeper you can find documentation which states the objectives of the EU-funded part of the project. The EU project?s title is "PyPy" which is an -acronym for "Researching a Highly Flexible and Modular Language Platform and +"acronym" for "Researching a Highly Flexible and Modular Language Platform and Implementing it by Leveraging the Open Source Python Language and Community". The EU-project has three objectives: one technical, one research-oriented and one methodology-oriented objective. In short PyPy is about building an @@ -132,28 +132,28 @@ +++++++++ The strategy of the project is to leverage the community of PyPy and Python -through open and transparent communication and working style. The challenge has -been to implement this strategy not only in the F/OSS community part of the -project but also in the partially funded consortium structure of the project. +through an open and transparent communication and working style. The challenge has +been to implement this strategy, not only in the F/OSS community part of the +project, but also in the partially funded consortium structure of the project. The structure of the project and the consortium needed to adhere to this strategy while also conforming to the actual requirements of the 6th Framework Programme. The F/OSS part of PyPy has no budget tied to it and no formal organizational structure. There are no resources tied to it other than the volunteers -participating in the development process, ranging from the core developers and -architects behind PyPy to people from all over the world, driven by a +participating in the development process. These are the core developers and +architects behind PyPy but also people from all over the world, driven by a combination of professional need and personal interest in Python language implementations such as PyPy and choosing to contribute to PyPy. There is also -a large group of students on PHD level participating and contributing, using -their areas of interest in PyPy as thesis material. +a large group of students on PHD levels participating and contributing, using +their areas of interest in PyPy as thesis materials. It is difficult to estimate the amount of people involved in PyPy but we -estimate that ca 300-500 people "follow actively" the progress of the project - +estimate that 300-500 people actively follow the progress of the project - this might mean reading emails, IRC logs and documentation in some cases, asking -questions and sending bug reports in other cases. There are ca 50 people that +questions and sending bug reports in others. There are around 50 people who have commit-rights to the source code. The core group of developers consists of -ca 10 people. +around 10 people. The EU part of the project is organized through a consortium which consists of 8 partners: DFKI (Germany), Ab Strakt (Sweden), Logilab (France), merlinux GmbH @@ -167,15 +167,15 @@ non-functional requirements that were formulated in a proposal and form the "Description of Work" in the contract with the European Commission. The funding received for this effort is 1.3 million euro. Of the core group of developers -mentioned above almost all of them (ca 10 people) are involved in some sense in +mentioned above almost all of them (10 people) are involved in some sense in the partner companies and organizations of the PyPy consortium. History: ++++++++ The ideas behind PyPy started via discussions on European mailing-lists in the -Python community late 2002 by people that had been active in the Python -community for some time, core developers interested in language implementation. +Python community late 2002 by people who had been active in the Python +community for some time; core developers interested in language implementation. They based the discussions and ideas partly on their experiences with developing and driving some well-known projects in the Python community. They met up in February 2003 at a "sprint", a one week working meeting,to draft @@ -205,7 +205,7 @@ The first funded year of the project ended with a review in Brussels in January 2006, hosted by the Commission, reviewing the 10 deliverables comprising the work of the first year. All deliverables were accepted and based on -recommendations by the external reviewers the consortium and the Commission is +recommendations by the external reviewers. The consortium and the Commission is now restructuring the volume of the remaining the deliverables (although not changing the scope of the project). @@ -218,13 +218,13 @@ Python is an Open Source language, published under an OSI approved open source license. It was created by Guido van Rossum and is now one of the five most used languages in the world. Due to the nature of the language there is a -strong focus on glue and integration with other languages such as C and Java -etc. Other typical aspects of the Python community is that it houses four large -language implementations as separate projects that communicate and discuss +strong focus on glue and integration with other languages such as C and Java. +Typical aspects of the Python community is that it houses four large +language implementations as separate projects which communicate and discuss their experiences and approaches with each other. This intra-extra community -focus and interest have created a collaborative atmosphere with an open and +focus and interest has created a collaborative atmosphere with an open and transparent communication climate. The key to a lively and working community is -the people factor, as always and of course so for the Python community as well. +the people factor, as always, and of course so for the Python community as well. The PyPy community ------------------ @@ -245,7 +245,7 @@ persons, participation funded privately. The effect on the evolving community was a stable subscriber participation on the development list of between 140-150 people. After the EU-funding and the more systematic structure of -sprinting every 6th week the amount of subscribers went from ca 150 people to +sprinting every 6th week the amount of subscribers went from around 150 people to over 250 people. @@ -255,14 +255,14 @@ The amount of collaborative focus and open and transparent communication in an open source community will manifest itself in the supporting infrastructure. In PyPy version control is the primary means of providing a secure platform for -incremental development. In PyPy, Subversion is being used, covering both -program files and documentation. Several automated mailing lists makes sure +incremental development. Subversion is used, covering both +program files and documentation. Several automated mailing lists make sure that every person involved receives instant notification on changes - supporting peer review on all levels. PyPy is also in some sense very much test-driven. PyPy is one of the primary users of a separate F/OSS project called the py.test, tools for automated -testing with PyPy developers contributing improvements to py.test. py.test +testing with PyPy developers contributing improvements to py.test. Py.test contains a sophisticated system for running tests against the Python Standard Library, with automatic selection of overriding tests in case there is internally developed code that overrides the Python Standard Library - @@ -273,8 +273,8 @@ in test results. The main communication channels between developers involved in PyPy is to -discuss over IRC (Internet-Relay-Chat) - open for all that are interested. -Several mailing lists for discussions and information is also used. Web pages, +discuss over IRC (Internet-Relay-Chat) - open for all who are interested. +Several mailing lists for discussions and information are also used. Web pages, documentation, tutorials, talks and papers etc are all available on the central developer server for everyone to access. A very useful feature that really supports information and communication (the author can attest to this from her own @@ -298,9 +298,9 @@ technical level. In a distributed and dispersed work style these two (social and technical) -levels needs to be consistent and support each other, discrepancies would be -immediately noticed. As stated before - the people factor is again evident and -in order to encourage participation and contribution there has to be trust as +levels needs to be consistent and support each other. Discrepancies would be +immediately noticed. As stated before - the people factor is again evident. +If you wish to encourage participation and contribution there has to be trust as well as a supportive environment in order to manage a virtual collaborative workspace. @@ -310,17 +310,17 @@ Another good example of the collaborative nature of the Python community is the way which the various projects share best practices. Core developers in the PyPy project picked up the practice of synchronization meetings as a powerful -way of supporting distributed and dispersed development, implemented by -Canonical. +way of supporting distributed and dispersed development. This practice was inspired +by the experiences of development processes at Canonical. -Sync-meetings are weekly short coordination meetings between developers, open -to all developers active in the PyPy community, usually but not necessarily +Sync-meetings are weekly short coordination meetings between developers. These are +open to all developers active in the PyPy community, usually but not necessarily involving aspects of EU-funded work on deliverables. These 30 minute IRC-meetings serve a weekly synchronization for regular discussions and integration of ongoing work. Meetings are prepared with an agenda sent out to pypy-dev and minutes are distributed on pypy-dev and archived in the repository -with publicly accessible links. Preparing, managing and documenting the meetings -is rotated between active developers and is self-organized as well. +with publicly accessible links. The work of preparing, managing and documenting the +meetings is rotated between active developers and is self-organized as well. Sync-meetings have proved to be a very good complement to a process in which the project sprints every 6th week. Sync-meetings keep cohesion as well as a @@ -352,7 +352,7 @@ committers collocated." The Zope community as well as other Python projects such as PyPy have seen that -sprints have goals beyond the creation of software: +sprints generate results beyond the creation of software: - It helped to evolve the community through participation and hands-on contact with the core developers. @@ -429,7 +429,7 @@ - a project co-coordinator managing contract administration and communication between consortium and the Commission -- a project manager, responsible for the project reaching it?s goals within the +- a project manager, responsible for the project reaching its goals within the time frame and budget The challenge was to design a project process that created a minimal amount of @@ -453,7 +453,7 @@ and coordinating the development work between the partners. This structure was the most difficult to design and implement due to the very -different nature of it?s purpose compared to the collaborative, self-organized +different nature of its purpose compared to the collaborative, self-organized nature of the F/OSS project - again it succeeded the way it has because of the core developers acting as an interface between the developer group and the consortium level work - again we see the trust aspect and the people factor in @@ -461,7 +461,7 @@ Sprints were budgeted for and designed into the process, together with a time plan for all deliverables. The project was divided into three different -phases, depending on the nature of the work flow. In that sense you could +phases, depending on the nature of the work flow. In that sense we could describe the EU-part of the project as a fixed-contract style of work, but with time plan, deliverables and work package descriptions on a high-level, not broken down into more granular tasks. @@ -473,7 +473,7 @@ incurred by each partner compared to budget, by the consortium on a specific work package and of the consortium overall. The consortium is free to reallocate budgeted man month funding between partners during the project. The project -reports costs per period - PyPy have two periods. +reports costs per period, PyPy has two periods. Again - the need for open and transparent communication together with a collaborative climate created the need to have what we believe a unique view on @@ -492,8 +492,8 @@ on consortium level work as is used in the development process. Interesting to note is that the technical reports written for the Commission regarding certain deliverables and progress have also been a great help towards the community who -also have free access to these reports and view them as extra, although -peculiar formated, documentation. +also has free access to these reports and view them as extra, although +peculiarly formated, documentation. Communication and documentation @@ -541,9 +541,9 @@ only software development but also sprint administration and planning as well as consortium work. -The majority of the partners on key roles in the consortium organization had -been working together since before the funding, procedures and best practices -had been tried out. The results from the first year showed that a minimalistic +The majority of the partners with key roles in the consortium organization had +been working together since before the funding. In that sense procedures and best +practices had been tried out. The results from the first year showed that a minimalistic path could be identified and that the important work would be to review and adjust the process when it did not support the work any more, or new situations arose that we had not planned for (and that did happen!). @@ -566,17 +566,17 @@ "open-door" policy that allowed us to fund non-consortium persons from the community to attend sprints. The budget was allocated, the procedure within the sprint context of handling more newcomers were known to us - the main -show stopper was that PyPy sprint funding did not fit within the customs and +show stopper was that the PyPy sprint funding did not fit within the customs and practices of contracts for cost claims in the Commission. -Every time we want to encourage participation and fund people to participate in -sprints and contribute the procedure now is that they have to join the -consortium as a full partner - but as a "physical person".This creates the need -for a contractual amendment which adds administrative work to the project as -well as for the persons in question. A too blunt instrument and today we still -do not have a working solution to this problem. It is an unfortunate example on -how the influencing factor of F/OSS, agile practices and EU-funding collides -and creates negative impact on the project. +Every time we want to encourage participation and fund non-consortium +people to participate in sprints and contribute, the procedure now is that +they have to join the consortium as a full partner. +This creates the need for a contractual amendment with the Commission which +adds administrative work to the project as well as for the persons in question. +A too blunt instrument and today we still do not have a working solution to this +problem. It is an unfortunate example on how the influencing factor of F/OSS, +agile practices and EU-funding collides and creates negative impact on the project. F/OSS community versus hierarchies for "conceptual integrity" @@ -584,17 +584,17 @@ There are many examples of F/OSS projects and communities that have dried out because of the fear of the architects to allow the contributors to fully -participate and also influence features and vision of the software. In PyPy +participate and also influence features and visions of the software. In PyPy this challenge comes twofold. Not only is there a challenge to let the core developers keep "conceptual integrity" while also allowing the community to influence the direction and features of the software. There is also the -consortium level of work in which the core developers could fear to "loose" the +consortium level of work in which the core developers could fear to "lose" the mandate of driving the architectural and design work. And yet another layer of risk and complexity would be if the consortium level would "shut the door" on the community, enforcing a more closed development process. As in many cases - being risk aware is the first step to mitigate. Because the -project is so deeply rooted in the F/OSS Python community, with it?s specific +project is so deeply rooted in the F/OSS Python community, with its specific culture and climate, and because so many people involved in the core work on both the development and consortium level also shared this background they took great pains to avoid situations like this to happen. In fact, what we have From arigo at codespeak.net Thu May 4 12:38:07 2006 From: arigo at codespeak.net (arigo at codespeak.net) Date: Thu, 4 May 2006 12:38:07 +0200 (CEST) Subject: [pypy-svn] r26757 - pypy/dist/pypy/objspace/std Message-ID: <20060504103807.16A0210092@code0.codespeak.net> Author: arigo Date: Thu May 4 12:38:03 2006 New Revision: 26757 Modified: pypy/dist/pypy/objspace/std/longobject.py Log: We now need to specialize this, for space.wrap(r_xxx()) where r_xxx can be various classes from rarithmetic. Modified: pypy/dist/pypy/objspace/std/longobject.py ============================================================================== --- pypy/dist/pypy/objspace/std/longobject.py (original) +++ pypy/dist/pypy/objspace/std/longobject.py Thu May 4 12:38:03 2006 @@ -618,7 +618,7 @@ #_________________________________________________________________ # Helper Functions -def args_from_long(l): #YYYYYY +def args_from_long(l): if l < 0: sign = -1 elif l > 0: @@ -634,7 +634,9 @@ if sign == 0: digits = [0] return digits, sign - +args_from_long._annspecialcase_ = "specialize:argtype(0)" +# ^^^ specialized by the precise type of 'l', which is typically a r_xxx +# instance from rpython.rarithmetic def _x_add(a, b): """ Add the absolute values of two long integers. """ From arigo at codespeak.net Thu May 4 14:29:53 2006 From: arigo at codespeak.net (arigo at codespeak.net) Date: Thu, 4 May 2006 14:29:53 +0200 (CEST) Subject: [pypy-svn] r26759 - in pypy/dist/pypy: rpython/memory translator/c/test Message-ID: <20060504122953.441AB10092@code0.codespeak.net> Author: arigo Date: Thu May 4 14:29:42 2006 New Revision: 26759 Modified: pypy/dist/pypy/rpython/memory/gctransform.py pypy/dist/pypy/translator/c/test/test_newgc.py Log: (arigo, cfbolz): test + fix for a case where the calculation of what needs to be saved accross a call was wrong. delete the whole special casing in framework gc transformer. This should be implemented more generally. Modified: pypy/dist/pypy/rpython/memory/gctransform.py ============================================================================== --- pypy/dist/pypy/rpython/memory/gctransform.py (original) +++ pypy/dist/pypy/rpython/memory/gctransform.py Thu May 4 14:29:42 2006 @@ -1009,36 +1009,7 @@ return newgcdependencies def protect_roots(self, op, livevars, block, index=-1): - livevars = dict.fromkeys( - [var for var in livevars if not var_ispyobj(var)], True) - if not needs_conservative_livevar_calculation(block): - not_needed = {} - if index == -1: - index = block.operations.index(op) # XXX hum - needed = {} - for before_op in block.operations[:index]: - if before_op.result not in livevars: - continue - if before_op.opname in ("cast_pointer", "same_as"): - not_needed[before_op.result] = True - elif before_op.opname in ("getfield", "getarrayitem"): - if (before_op.args[0] in livevars or - isinstance(before_op.args[0], Constant)): - not_needed[before_op.result] = True - for after_op in block.operations[index:]: - for arg in after_op.args: - needed[arg] = True - needed[after_op.result] = True - for exit in block.exits: - for arg in exit.args: - needed[arg] = True - newlivevars = [] - for var in livevars: - if var in needed and var not in not_needed: - newlivevars.append(var) - livevars = newlivevars - else: - livevars = livevars.keys() + livevars = [var for var in livevars if not var_ispyobj(var)] newops = list(self.push_roots(livevars)) index = len(newops) newops.append(op) Modified: pypy/dist/pypy/translator/c/test/test_newgc.py ============================================================================== --- pypy/dist/pypy/translator/c/test/test_newgc.py (original) +++ pypy/dist/pypy/translator/c/test/test_newgc.py Thu May 4 14:29:42 2006 @@ -332,6 +332,34 @@ assert res == 42 assert len([op for op in startblock.operations if op.opname == "gc_reload_possibly_moved"]) == 0 + def test_framework_protect_getfield(self): + class A(object): + pass + class B(object): + pass + def prepare(b, n): + a = A() + a.value = n + b.a = a + b.othervalue = 5 + def g(a): + # this should trigger 3 collections + for i in range(1000000): + prepare(B(), -1) + # we need to prevent it getting inlined + if not a: + g(A()) + return a.value + def f(): + b = B() + prepare(b, 123) + a = b.a + b.a = None + return g(a) + b.othervalue + fn = self.getcompiled(f) + res = fn() + assert res == 128 + def test_framework_varsized(self): S = lltype.GcStruct("S", ('x', lltype.Signed)) T = lltype.GcStruct("T", ('y', lltype.Signed), From arigo at codespeak.net Thu May 4 14:38:19 2006 From: arigo at codespeak.net (arigo at codespeak.net) Date: Thu, 4 May 2006 14:38:19 +0200 (CEST) Subject: [pypy-svn] r26760 - pypy/dist/pypy/rpython/memory Message-ID: <20060504123819.2762F10094@code0.codespeak.net> Author: arigo Date: Thu May 4 14:38:18 2006 New Revision: 26760 Modified: pypy/dist/pypy/rpython/memory/gc.py Log: (arigo, cfbolz): add debug prints to collect. This might be annoying but gives interesting insights to how often collections happen and what gets collected Modified: pypy/dist/pypy/rpython/memory/gc.py ============================================================================== --- pypy/dist/pypy/rpython/memory/gc.py (original) +++ pypy/dist/pypy/rpython/memory/gc.py Thu May 4 14:38:18 2006 @@ -170,7 +170,8 @@ return result + size_gc_header def collect(self): -## print "collecting" + import os + os.write(2, 'collecting... ') self.bytes_malloced = 0 roots = self.get_roots() objects = self.AddressLinkedList() @@ -237,11 +238,11 @@ else: freed_size += size + MarkSweepGC._size_gc_header raw_free(curr) -## print "free %s bytes. the heap is %s bytes." % (freed_size, curr_heap_size) free_non_gc_object(self.malloced_objects) self.malloced_objects = newmo if curr_heap_size > self.heap_size: self.heap_size = curr_heap_size + os.write(2, "freed %s bytes. the heap is now %s bytes.\n" % (freed_size, curr_heap_size)) def size_gc_header(self, typeid=0): return MarkSweepGC._size_gc_header From cfbolz at codespeak.net Thu May 4 15:19:54 2006 From: cfbolz at codespeak.net (cfbolz at codespeak.net) Date: Thu, 4 May 2006 15:19:54 +0200 (CEST) Subject: [pypy-svn] r26761 - pypy/extradoc/talk/agile2006 Message-ID: <20060504131954.A8890100A7@code0.codespeak.net> Author: cfbolz Date: Thu May 4 15:19:53 2006 New Revision: 26761 Modified: pypy/extradoc/talk/agile2006/draftpaper_agile2006.pdf pypy/extradoc/talk/agile2006/draftpaper_agile2006.txt Log: fix quotes and regenerate pdf Modified: pypy/extradoc/talk/agile2006/draftpaper_agile2006.pdf ============================================================================== Binary files. No diff available. Modified: pypy/extradoc/talk/agile2006/draftpaper_agile2006.txt ============================================================================== --- pypy/extradoc/talk/agile2006/draftpaper_agile2006.txt (original) +++ pypy/extradoc/talk/agile2006/draftpaper_agile2006.txt Thu May 4 15:19:53 2006 @@ -2,6 +2,7 @@ Trouble in Paradise: Open Source projects, EU-funding and Agile practices =================================================================================== +.. sectnum .. raw:: latex \author{Beatrice During} @@ -88,7 +89,7 @@ Our conclusion so far in the project is that we believe that the practice of "sprinting", as being used in the PyPy project, makes Agile and - Distributed/dispersed work styles more possible to combine. We also believe it +Distributed/dispersed work styles more possible to combine. We also believe it is a very useful practice for creating value and ensuring quality in projects with hybrid cultures and methodologies. It is our aim to start to show-case this with experiences from the first funded year of PyPy. We also feel that our @@ -344,12 +345,12 @@ method as it is used in the Python community says the following about how they evolved the method during 2001 and 2002: -"The motivation was to begin using as much of XP as would fit to accelerate -Zope3 development. Given the different development culture of the Zope -community (framework-centric, distributed, no "business user" present), some of -the XP mantras /practices couldn't be done directly. We decided to try to do -"as much XP as possible" for short, highly-focused sessions, with all active -committers collocated." + *"The motivation was to begin using as much of XP as would fit to + accelerate Zope3 development. Given the different development culture of + the Zope community (framework-centric, distributed, no "business user" + present), some of the XP mantras /practices couldn't be done directly. We + decided to try to do "as much XP as possible" for short, highly-focused + sessions, with all active committers collocated."* The Zope community as well as other Python projects such as PyPy have seen that sprints generate results beyond the creation of software: @@ -369,12 +370,12 @@ The reason for naming the method sprinting, not at all connected to Scrum and the usage of sprints in that context, according to Tres Seaver is: -"... because of the fact that we weren't doing XP in its proper sense, which is -more like running a long-distance race, where pacing oneself is critical. -Instead, we were pushing as fast as possible in order to maximize the benefit -of limited face time. Of all the XP practices, the one we gave shortest shrift -to is "no overtime": as sprints often go far into the evening (or even the wee -hours of the morning." + *"... because of the fact that we weren't doing XP in its proper sense, + which is more like running a long-distance race, where pacing oneself is + critical. Instead, we were pushing as fast as possible in order to + maximize the benefit of limited face time. Of all the XP practices, the + one we gave shortest shrift to is "no overtime": as sprints often go far + into the evening (or even the wee hours of the morning."* To summarize the results of this first try out of the methodology shows that sprinting was the driver for making Zope3 a community-driven project: Zope From arigo at codespeak.net Thu May 4 15:26:40 2006 From: arigo at codespeak.net (arigo at codespeak.net) Date: Thu, 4 May 2006 15:26:40 +0200 (CEST) Subject: [pypy-svn] r26762 - in pypy/dist/pypy/translator/backendopt: . test Message-ID: <20060504132640.703BF10095@code0.codespeak.net> Author: arigo Date: Thu May 4 15:26:39 2006 New Revision: 26762 Modified: pypy/dist/pypy/translator/backendopt/malloc.py pypy/dist/pypy/translator/backendopt/test/test_malloc.py Log: Fix and test for another malloc removal bug. Modified: pypy/dist/pypy/translator/backendopt/malloc.py ============================================================================== --- pypy/dist/pypy/translator/backendopt/malloc.py (original) +++ pypy/dist/pypy/translator/backendopt/malloc.py Thu May 4 15:26:39 2006 @@ -214,10 +214,10 @@ direct_fieldptr_key[ARRAY, 'item0'] = S, S._names[0] for name in S._names[start:]: key = S, name - flatnames.append(key) FIELDTYPE = S._flds[name] if key in accessed_substructs: needsubmallocs.append(key) + flatnames.append(key) newvarstype[key] = lltype.Ptr(lltype.GcStruct('wrapper', ('data', FIELDTYPE))) elif not isinstance(FIELDTYPE, lltype.ContainerType): @@ -225,6 +225,7 @@ constant = Constant(example) constant.concretetype = FIELDTYPE flatconstants[key] = constant + flatnames.append(key) newvarstype[key] = FIELDTYPE #else: # the inlined substructure is never accessed, drop it Modified: pypy/dist/pypy/translator/backendopt/test/test_malloc.py ============================================================================== --- pypy/dist/pypy/translator/backendopt/test/test_malloc.py (original) +++ pypy/dist/pypy/translator/backendopt/test/test_malloc.py Thu May 4 15:26:39 2006 @@ -6,6 +6,7 @@ from pypy.translator import simplify from pypy.objspace.flow.model import checkgraph, flatten, Block from pypy.rpython.llinterp import LLInterpreter +from pypy.rpython.lltypesystem import lltype from pypy.conftest import option def check_malloc_removed(graph): @@ -154,7 +155,6 @@ assert op.opname == "malloc" def test_add_keepalives(): - from pypy.rpython.lltypesystem import lltype class A: pass SMALL = lltype.Struct('SMALL', ('x', lltype.Signed)) @@ -171,7 +171,6 @@ check(fn7, [int], [10], 55, must_be_removed=False) def test_getsubstruct(): - from pypy.rpython.lltypesystem import lltype SMALL = lltype.Struct('SMALL', ('x', lltype.Signed)) BIG = lltype.GcStruct('BIG', ('z', lltype.Signed), ('s', SMALL)) @@ -184,7 +183,6 @@ check(fn, [int, int], [100, 58], 42) def test_fixedsizearray(): - from pypy.rpython.lltypesystem import lltype A = lltype.FixedSizeArray(lltype.Signed, 3) S = lltype.GcStruct('S', ('a', A)) @@ -198,7 +196,6 @@ check(fn, [int, int], [100, 42], 58) def test_wrapper_cannot_be_removed(): - from pypy.rpython.lltypesystem import lltype SMALL = lltype.OpaqueType('SMALL') BIG = lltype.GcStruct('BIG', ('z', lltype.Signed), ('s', SMALL)) @@ -211,7 +208,6 @@ check(fn, [], [], None, must_be_removed=False) def test_direct_fieldptr(): - from pypy.rpython.lltypesystem import lltype S = lltype.GcStruct('S', ('x', lltype.Signed)) def fn(): @@ -223,7 +219,6 @@ check(fn, [], [], 11) def test_direct_fieldptr_2(): - from pypy.rpython.lltypesystem import lltype T = lltype.GcStruct('T', ('z', lltype.Signed)) S = lltype.GcStruct('S', ('t', T), ('x', lltype.Signed), @@ -241,7 +236,6 @@ check(fn, [], [], 42) def test_getarraysubstruct(): - from pypy.rpython.lltypesystem import lltype U = lltype.Struct('U', ('n', lltype.Signed)) for length in [1, 2]: S = lltype.GcStruct('S', ('a', lltype.FixedSizeArray(U, length))) @@ -254,9 +248,18 @@ check(fn, [], [], 12) def test_ptr_nonzero(): - from pypy.rpython.lltypesystem import lltype S = lltype.GcStruct('S') def fn(): s = lltype.malloc(S) return bool(s) check(fn, [], [], True) + +def test_substruct_not_accessed(): + SMALL = lltype.Struct('SMALL', ('x', lltype.Signed)) + BIG = lltype.GcStruct('BIG', ('z', lltype.Signed), ('s', SMALL)) + def fn(): + x = lltype.malloc(BIG) + while x.z < 10: # makes several blocks + x.z += 3 + return x.z + check(fn, [], [], 12) From arigo at codespeak.net Thu May 4 16:23:40 2006 From: arigo at codespeak.net (arigo at codespeak.net) Date: Thu, 4 May 2006 16:23:40 +0200 (CEST) Subject: [pypy-svn] r26763 - pypy/dist/pypy/annotation Message-ID: <20060504142340.1578710095@code0.codespeak.net> Author: arigo Date: Thu May 4 16:23:38 2006 New Revision: 26763 Modified: pypy/dist/pypy/annotation/bookkeeper.py pypy/dist/pypy/annotation/builtin.py pypy/dist/pypy/annotation/dictdef.py Log: r_dicts don't actually need the hash of their keys, as they delegate its computation to callbacks. Modified: pypy/dist/pypy/annotation/bookkeeper.py ============================================================================== --- pypy/dist/pypy/annotation/bookkeeper.py (original) +++ pypy/dist/pypy/annotation/bookkeeper.py Thu May 4 16:23:38 2006 @@ -274,12 +274,13 @@ listdef.generalize(s_value) return SomeList(listdef) - def getdictdef(self): + def getdictdef(self, is_r_dict=False): """Get the DictDef associated with the current position.""" try: dictdef = self.dictdefs[self.position_key] except KeyError: - dictdef = self.dictdefs[self.position_key] = DictDef(self) + dictdef = DictDef(self, is_r_dict=is_r_dict) + self.dictdefs[self.position_key] = dictdef return dictdef def newdict(self, *items_s): Modified: pypy/dist/pypy/annotation/builtin.py ============================================================================== --- pypy/dist/pypy/annotation/builtin.py (original) +++ pypy/dist/pypy/annotation/builtin.py Thu May 4 16:23:38 2006 @@ -287,7 +287,7 @@ return immutablevalue(True) def robjmodel_r_dict(s_eqfn, s_hashfn): - dictdef = getbookkeeper().getdictdef() + dictdef = getbookkeeper().getdictdef(is_r_dict=True) dictdef.dictkey.update_rdict_annotations(s_eqfn, s_hashfn) return SomeDict(dictdef) Modified: pypy/dist/pypy/annotation/dictdef.py ============================================================================== --- pypy/dist/pypy/annotation/dictdef.py (original) +++ pypy/dist/pypy/annotation/dictdef.py Thu May 4 16:23:38 2006 @@ -7,8 +7,9 @@ class DictKey(ListItem): custom_eq_hash = False - def __init__(self, bookkeeper, s_value): + def __init__(self, bookkeeper, s_value, is_r_dict=False): ListItem.__init__(self, bookkeeper, s_value) + self.is_r_dict = is_r_dict self.enable_hashing() def patch(self): @@ -26,7 +27,8 @@ other=other) def enable_hashing(self): - if isinstance(self.s_value, SomeInstance): + # r_dicts don't need the RPython hash of their keys + if isinstance(self.s_value, SomeInstance) and not self.is_r_dict: self.bookkeeper.needs_hash_support[self.s_value.classdef] = True def generalize(self, s_other_value): @@ -90,8 +92,9 @@ DictDef stores.""" def __init__(self, bookkeeper, s_key = SomeImpossibleValue(), - s_value = SomeImpossibleValue()): - self.dictkey = DictKey(bookkeeper, s_key) + s_value = SomeImpossibleValue(), + is_r_dict = False): + self.dictkey = DictKey(bookkeeper, s_key, is_r_dict) self.dictkey.itemof[self] = True self.dictvalue = DictValue(bookkeeper, s_value) self.dictvalue.itemof[self] = True From arigo at codespeak.net Thu May 4 16:26:08 2006 From: arigo at codespeak.net (arigo at codespeak.net) Date: Thu, 4 May 2006 16:26:08 +0200 (CEST) Subject: [pypy-svn] r26764 - pypy/dist/pypy/annotation Message-ID: <20060504142608.C55B210095@code0.codespeak.net> Author: arigo Date: Thu May 4 16:26:08 2006 New Revision: 26764 Modified: pypy/dist/pypy/annotation/bookkeeper.py Log: Forgot prebuilt r_dicts. Modified: pypy/dist/pypy/annotation/bookkeeper.py ============================================================================== --- pypy/dist/pypy/annotation/bookkeeper.py (original) +++ pypy/dist/pypy/annotation/bookkeeper.py Thu May 4 16:26:08 2006 @@ -344,7 +344,8 @@ except KeyError: result = SomeDict(DictDef(self, SomeImpossibleValue(), - SomeImpossibleValue())) + SomeImpossibleValue(), + is_r_dict = tp is r_dict)) self.immutable_cache[key] = result if tp is r_dict: s_eqfn = self.immutablevalue(x.key_eq) From pedronis at codespeak.net Thu May 4 17:26:23 2006 From: pedronis at codespeak.net (pedronis at codespeak.net) Date: Thu, 4 May 2006 17:26:23 +0200 (CEST) Subject: [pypy-svn] r26765 - in pypy/dist/pypy: annotation annotation/test rpython/test Message-ID: <20060504152623.850BB10092@code0.codespeak.net> Author: pedronis Date: Thu May 4 17:26:21 2006 New Revision: 26765 Modified: pypy/dist/pypy/annotation/description.py pypy/dist/pypy/annotation/test/test_annrpython.py pypy/dist/pypy/rpython/test/test_rclass.py Log: test and fix about _mixin_ Modified: pypy/dist/pypy/annotation/description.py ============================================================================== --- pypy/dist/pypy/annotation/description.py (original) +++ pypy/dist/pypy/annotation/description.py Thu May 4 17:26:21 2006 @@ -336,7 +336,7 @@ if getattr(b1, '_mixin_', False): assert b1.__bases__ == () or b1.__bases__ == (object,), ( "mixin class %r should have no base" % (b1,)) - self.add_sources_for_class(b1) + self.add_sources_for_class(b1, mixin=True) else: assert base is object, ("multiple inheritance only supported " "with _mixin_: %r" % (cls,)) @@ -346,7 +346,7 @@ if base is not object: self.basedesc = bookkeeper.getdesc(base) - def add_sources_for_class(self, cls): + def add_sources_for_class(self, cls, mixin=False): for name, value in cls.__dict__.items(): ## -- useless? -- ignore some special attributes ##if name.startswith('_') and not isinstance(value, types.FunctionType): @@ -355,7 +355,7 @@ # for debugging if not hasattr(value, 'class_'): value.class_ = self.pyobj # remember that this is really a method - if self.specialize: + if self.specialize or mixin: # make a custom funcdesc that specializes on its first # argument (i.e. 'self'). from pypy.annotation.specialize import specialize_argtype Modified: pypy/dist/pypy/annotation/test/test_annrpython.py ============================================================================== --- pypy/dist/pypy/annotation/test/test_annrpython.py (original) +++ pypy/dist/pypy/annotation/test/test_annrpython.py Thu May 4 17:26:21 2006 @@ -2002,6 +2002,35 @@ assert s.is_constant() assert s.const == 0 + def test_mixin(self): + class Mixin(object): + _mixin_ = True + + def m(self, v): + return v + + class Base(object): + pass + + class A(Base, Mixin): + pass + + class B(Base, Mixin): + pass + + def f(): + a = A() + v0 = a.m(2) + b = B() + v1 = b.m('x') + return v0, v1 + + a = self.RPythonAnnotator() + s = a.build_types(f, []) + assert isinstance(s.items[0], annmodel.SomeInteger) + assert isinstance(s.items[1], annmodel.SomeChar) + + def g(n): return [0,1,2,n] 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 May 4 17:26:21 2006 @@ -432,7 +432,32 @@ res = interpret(f, [], type_system=self.ts) assert res == 1 - + def test_mixin(self): + class Mixin(object): + _mixin_ = True + + def m(self, v): + return v + + class Base(object): + pass + + class A(Base, Mixin): + pass + + class B(Base, Mixin): + pass + + def f(): + a = A() + v0 = a.m(2) + b = B() + v1 = b.m('x') + return v0, v1 + + res = interpret(f, [], type_system=self.ts) + assert typeOf(res.item0) == Signed + class TestLltype(BaseTestRclass): From cfbolz at codespeak.net Fri May 5 00:15:16 2006 From: cfbolz at codespeak.net (cfbolz at codespeak.net) Date: Fri, 5 May 2006 00:15:16 +0200 (CEST) Subject: [pypy-svn] r26767 - pypy/dist/pypy/objspace/std/test Message-ID: <20060504221516.68AA110089@code0.codespeak.net> Author: cfbolz Date: Fri May 5 00:15:13 2006 New Revision: 26767 Removed: pypy/dist/pypy/objspace/std/test/broken_test_floatobject.py pypy/dist/pypy/objspace/std/test/broken_test_template.py Log: remove two totally ancient test files that seems to predate py.test. I am very sure that they are not useful anymore. From cfbolz at codespeak.net Fri May 5 00:36:24 2006 From: cfbolz at codespeak.net (cfbolz at codespeak.net) Date: Fri, 5 May 2006 00:36:24 +0200 (CEST) Subject: [pypy-svn] r26769 - in pypy/dist/pypy: annotation annotation/test rpython/test Message-ID: <20060504223624.D9C1B10090@code0.codespeak.net> Author: cfbolz Date: Fri May 5 00:36:17 2006 New Revision: 26769 Modified: pypy/dist/pypy/annotation/description.py pypy/dist/pypy/annotation/test/test_annrpython.py pypy/dist/pypy/rpython/test/test_rclass.py Log: make it possible to inherit from classes that have a mixin Modified: pypy/dist/pypy/annotation/description.py ============================================================================== --- pypy/dist/pypy/annotation/description.py (original) +++ pypy/dist/pypy/annotation/description.py Fri May 5 00:36:17 2006 @@ -333,7 +333,7 @@ for b1 in baselist: if b1 is object: continue - if getattr(b1, '_mixin_', False): + if b1.__dict__.get('_mixin_', False): assert b1.__bases__ == () or b1.__bases__ == (object,), ( "mixin class %r should have no base" % (b1,)) self.add_sources_for_class(b1, mixin=True) Modified: pypy/dist/pypy/annotation/test/test_annrpython.py ============================================================================== --- pypy/dist/pypy/annotation/test/test_annrpython.py (original) +++ pypy/dist/pypy/annotation/test/test_annrpython.py Fri May 5 00:36:17 2006 @@ -2018,17 +2018,23 @@ class B(Base, Mixin): pass + class C(B): + pass + def f(): a = A() v0 = a.m(2) b = B() v1 = b.m('x') - return v0, v1 + c = C() + v2 = c.m('y') + return v0, v1, v2 a = self.RPythonAnnotator() s = a.build_types(f, []) assert isinstance(s.items[0], annmodel.SomeInteger) assert isinstance(s.items[1], annmodel.SomeChar) + assert isinstance(s.items[2], annmodel.SomeChar) def g(n): 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 May 5 00:36:17 2006 @@ -448,12 +448,17 @@ class B(Base, Mixin): pass + class C(B): + pass + def f(): a = A() v0 = a.m(2) b = B() v1 = b.m('x') - return v0, v1 + c = C() + v2 = c.m('y') + return v0, v1, v2 res = interpret(f, [], type_system=self.ts) assert typeOf(res.item0) == Signed From arigo at codespeak.net Fri May 5 00:36:25 2006 From: arigo at codespeak.net (arigo at codespeak.net) Date: Fri, 5 May 2006 00:36:25 +0200 (CEST) Subject: [pypy-svn] r26770 - in pypy/dist/pypy: annotation rpython rpython/lltypesystem rpython/lltypesystem/test rpython/ootypesystem rpython/test Message-ID: <20060504223625.8C3FC10089@code0.codespeak.net> Author: arigo Date: Fri May 5 00:36:20 2006 New Revision: 26770 Added: pypy/dist/pypy/rpython/lltypesystem/rtagged.py (contents, props changed) pypy/dist/pypy/rpython/lltypesystem/test/test_rtagged.py (contents, props changed) Modified: pypy/dist/pypy/annotation/builtin.py pypy/dist/pypy/rpython/llinterp.py pypy/dist/pypy/rpython/lltypesystem/lloperation.py pypy/dist/pypy/rpython/lltypesystem/lltype.py pypy/dist/pypy/rpython/lltypesystem/rbuiltin.py pypy/dist/pypy/rpython/lltypesystem/rclass.py pypy/dist/pypy/rpython/lltypesystem/rpbc.py pypy/dist/pypy/rpython/lltypesystem/test/test_lltype.py pypy/dist/pypy/rpython/objectmodel.py pypy/dist/pypy/rpython/ootypesystem/rclass.py pypy/dist/pypy/rpython/rbuiltin.py pypy/dist/pypy/rpython/rclass.py pypy/dist/pypy/rpython/test/test_rptr.py Log: (pedronis, arigo) Started support for tagged pointers. A lot of hacks, but it didn't take too long. See test_rtagged.py. Modified: pypy/dist/pypy/annotation/builtin.py ============================================================================== --- pypy/dist/pypy/annotation/builtin.py (original) +++ pypy/dist/pypy/annotation/builtin.py Fri May 5 00:36:20 2006 @@ -314,6 +314,9 @@ def robjmodel_hint(s, **kwds_s): return s +def robjmodel_getvalue_from_unboxed(s): + return SomeInteger() + def llmemory_cast_ptr_to_adr(s): return SomeAddress() @@ -370,6 +373,8 @@ BUILTIN_ANALYZERS[pypy.rpython.objectmodel.hlinvoke] = robjmodel_hlinvoke BUILTIN_ANALYZERS[pypy.rpython.objectmodel.keepalive_until_here] = robjmodel_keepalive_until_here BUILTIN_ANALYZERS[pypy.rpython.objectmodel.hint] = robjmodel_hint +BUILTIN_ANALYZERS[pypy.rpython.objectmodel.getvalue_from_unboxed] = \ + robjmodel_getvalue_from_unboxed BUILTIN_ANALYZERS[pypy.rpython.lltypesystem.llmemory.cast_ptr_to_adr] = llmemory_cast_ptr_to_adr BUILTIN_ANALYZERS[pypy.rpython.lltypesystem.llmemory.cast_adr_to_ptr] = llmemory_cast_adr_to_ptr BUILTIN_ANALYZERS[pypy.rpython.lltypesystem.llmemory.cast_adr_to_int] = llmemory_cast_adr_to_int @@ -443,6 +448,10 @@ def cast_ptr_to_int(s_ptr): # xxx return SomeInteger() +def cast_int_to_ptr(PtrT, s_int): + assert PtrT.is_constant() + return SomePtr(ll_ptrtype=PtrT.const) + def getRuntimeTypeInfo(T): assert T.is_constant() return immutablevalue(lltype.getRuntimeTypeInfo(T.const)) @@ -460,6 +469,7 @@ BUILTIN_ANALYZERS[lltype.direct_arrayitems] = direct_arrayitems BUILTIN_ANALYZERS[lltype.direct_ptradd] = direct_ptradd BUILTIN_ANALYZERS[lltype.cast_ptr_to_int] = cast_ptr_to_int +BUILTIN_ANALYZERS[lltype.cast_int_to_ptr] = cast_int_to_ptr BUILTIN_ANALYZERS[lltype.getRuntimeTypeInfo] = getRuntimeTypeInfo BUILTIN_ANALYZERS[lltype.runtime_type_info] = runtime_type_info Modified: pypy/dist/pypy/rpython/llinterp.py ============================================================================== --- pypy/dist/pypy/rpython/llinterp.py (original) +++ pypy/dist/pypy/rpython/llinterp.py Fri May 5 00:36:20 2006 @@ -334,7 +334,8 @@ assert isinstance(operation.args[0], Variable) vals = [self.getval(x) for x in operation.args] # if these special cases pile up, do something better here - if operation.opname in ['cast_pointer', 'ooupcast', 'oodowncast', 'cast_adr_to_ptr']: + if operation.opname in ['cast_pointer', 'ooupcast', 'oodowncast', + 'cast_adr_to_ptr', 'cast_int_to_ptr']: vals.insert(0, operation.result.concretetype) try: retval = ophandler(*vals) @@ -608,6 +609,9 @@ assert isinstance(lltype.typeOf(ptr1).TO, (lltype.Array, lltype.Struct)) return lltype.cast_ptr_to_int(ptr1) + def op_cast_int_to_ptr(self, tp, int1): + return lltype.cast_int_to_ptr(tp, int1) + def op_cast_ptr_to_adr(self, ptr): assert checkptr(ptr) return llmemory.cast_ptr_to_adr(ptr) Modified: pypy/dist/pypy/rpython/lltypesystem/lloperation.py ============================================================================== --- pypy/dist/pypy/rpython/lltypesystem/lloperation.py (original) +++ pypy/dist/pypy/rpython/lltypesystem/lloperation.py Fri May 5 00:36:20 2006 @@ -266,6 +266,7 @@ 'ptr_nonzero': LLOp(canfold=True), 'ptr_iszero': LLOp(canfold=True), 'cast_ptr_to_int': LLOp(sideeffects=False), + 'cast_int_to_ptr': LLOp(sideeffects=False), 'direct_fieldptr': LLOp(canfold=True), 'direct_arrayitems': LLOp(canfold=True), 'direct_ptradd': LLOp(canfold=True), Modified: pypy/dist/pypy/rpython/lltypesystem/lltype.py ============================================================================== --- pypy/dist/pypy/rpython/lltypesystem/lltype.py (original) +++ pypy/dist/pypy/rpython/lltypesystem/lltype.py Fri May 5 00:36:20 2006 @@ -870,6 +870,8 @@ return self if not self: # null pointer cast return PTRTYPE._defl() + if isinstance(self._obj, int): + return _ptr(PTRTYPE, self._obj, solid=True) if down_or_up > 0: p = self while down_or_up: @@ -893,9 +895,15 @@ def _cast_to_int(self): obj = self._obj + if isinstance(obj, int): + return obj # special case for cast_int_to_ptr() results while obj._parentstructure(): obj = obj._parentstructure() - return id(obj) + result = id(obj) + # assume that id() returns an addressish value which is + # not zero and aligned to at least a multiple of 4 + assert result != 0 and (result & 3) == 0 + return result def _cast_to_adr(self): from pypy.rpython.lltypesystem import llmemory @@ -1265,6 +1273,10 @@ def cast_ptr_to_int(ptr): return ptr._cast_to_int() +def cast_int_to_ptr(PTRTYPE, oddint): + assert oddint & 1, "only odd integers can be cast back to ptr" + return _ptr(PTRTYPE, oddint, solid=True) + def attachRuntimeTypeInfo(GCSTRUCT, funcptr=None, destrptr=None): if not isinstance(GCSTRUCT, GcStruct): raise TypeError, "expected a GcStruct: %s" % GCSTRUCT Modified: pypy/dist/pypy/rpython/lltypesystem/rbuiltin.py ============================================================================== --- pypy/dist/pypy/rpython/lltypesystem/rbuiltin.py (original) +++ pypy/dist/pypy/rpython/lltypesystem/rbuiltin.py Fri May 5 00:36:20 2006 @@ -24,24 +24,8 @@ cnone = hop.inputconst(rlist, None) return hop.genop('ptr_ne', [vlist, cnone], resulttype=lltype.Bool) - class_repr = rclass.get_type_repr(hop.rtyper) assert isinstance(hop.args_r[0], rclass.InstanceRepr) - instance_repr = hop.args_r[0].common_repr() - - v_obj, v_cls = hop.inputargs(instance_repr, class_repr) - if isinstance(v_cls, Constant): - cls = v_cls.value - # XXX re-implement the following optimization - #if cls.subclassrange_max == cls.subclassrange_min: - # # a class with no subclass - # return hop.gendirectcall(rclass.ll_isinstance_exact, v_obj, v_cls) - #else: - minid = hop.inputconst(lltype.Signed, cls.subclassrange_min) - maxid = hop.inputconst(lltype.Signed, cls.subclassrange_max) - return hop.gendirectcall(rclass.ll_isinstance_const, v_obj, minid, - maxid) - else: - return hop.gendirectcall(rclass.ll_isinstance, v_obj, v_cls) + return hop.args_r[0].rtype_isinstance(hop) def ll_instantiate(typeptr): # NB. used by rpbc.ClassesPBCRepr as well my_instantiate = typeptr.instantiate @@ -75,8 +59,13 @@ c = hop.inputconst(pyobj_repr, __import__) return hop.genop('simple_call', [c] + args_v, resulttype = pyobj_repr) +def rtype_getvalue_from_unboxed(hop): + from pypy.rpython.lltypesystem.rtagged import rtype_getvalue_from_unboxed + return rtype_getvalue_from_unboxed(hop) + BUILTIN_TYPER = {} BUILTIN_TYPER[objectmodel.instantiate] = rtype_instantiate +BUILTIN_TYPER[objectmodel.getvalue_from_unboxed] = rtype_getvalue_from_unboxed BUILTIN_TYPER[isinstance] = rtype_builtin_isinstance BUILTIN_TYPER[hasattr] = rtype_builtin_hasattr BUILTIN_TYPER[__import__] = rtype_builtin___import__ Modified: pypy/dist/pypy/rpython/lltypesystem/rclass.py ============================================================================== --- pypy/dist/pypy/rpython/lltypesystem/rclass.py (original) +++ pypy/dist/pypy/rpython/lltypesystem/rclass.py Fri May 5 00:36:20 2006 @@ -20,6 +20,7 @@ from pypy.rpython.robject import PyObjRepr, pyobj_repr from pypy.rpython.extregistry import ExtRegistryEntry from pypy.annotation import model as annmodel +from pypy.rpython.objectmodel import UnboxedValue # # There is one "vtable" per user class, with the following structure: @@ -64,7 +65,8 @@ ('subclassrange_max', Signed), ('rtti', Ptr(RuntimeTypeInfo)), ('name', Ptr(Array(Char))), - ('instantiate', Ptr(FuncType([], OBJECTPTR))))) + ('instantiate', Ptr(FuncType([], OBJECTPTR))), + hints = {'immutable': True})) # non-gc case NONGCOBJECT = Struct('nongcobject', ('typeptr', CLASSTYPE)) NONGCOBJECTPTR = Ptr(OBJECT) @@ -121,9 +123,10 @@ # self.rbase = getclassrepr(self.rtyper, self.classdef.basedef) self.rbase.setup() + kwds = {'hints': {'immutable': True}} vtable_type = Struct('%s_vtable' % self.classdef.name, ('super', self.rbase.vtable_type), - *llfields) + *llfields, **kwds) self.vtable_type.become(vtable_type) allmethods.update(self.rbase.allmethods) self.clsfields = clsfields @@ -473,7 +476,7 @@ raise MissingRTypeAttribute(attr) self.rbase.setfield(vinst, attr, vvalue, llops, force_cast=True, opname=opname) - def new_instance(self, llops): + def new_instance(self, llops, classcallhop=None): """Build a new instance, without calling __init__.""" mallocop = 'malloc' ctype = inputconst(Void, self.object_type) @@ -550,6 +553,44 @@ rstr.ll_strconcat(nameString, rstr.instance_str_suffix)) + def rtype_isinstance(self, hop): + class_repr = get_type_repr(hop.rtyper) + instance_repr = self.common_repr() + + v_obj, v_cls = hop.inputargs(instance_repr, class_repr) + if isinstance(v_cls, Constant): + cls = v_cls.value + # XXX re-implement the following optimization + #if cls.subclassrange_max == cls.subclassrange_min: + # # a class with no subclass + # return hop.gendirectcall(rclass.ll_isinstance_exact, v_obj, v_cls) + #else: + minid = hop.inputconst(Signed, cls.subclassrange_min) + maxid = hop.inputconst(Signed, cls.subclassrange_max) + return hop.gendirectcall(ll_isinstance_const, v_obj, minid, maxid) + else: + return hop.gendirectcall(ll_isinstance, v_obj, v_cls) + + +def buildinstancerepr(rtyper, classdef, does_need_gc=True): + if classdef is None: + unboxed = [] + else: + unboxed = [subdef for subdef in classdef.getallsubdefs() + if subdef.classdesc.pyobj is not None and + issubclass(subdef.classdesc.pyobj, UnboxedValue)] + if len(unboxed) == 0: + return InstanceRepr(rtyper, classdef, does_need_gc) + else: + # the UnboxedValue class and its parent classes need a + # special repr for their instances + if len(unboxed) != 1: + raise TyperError("%r has several UnboxedValue subclasses" % ( + classdef,)) + assert does_need_gc + from pypy.rpython.lltypesystem import rtagged + return rtagged.TaggedInstanceRepr(rtyper, classdef, unboxed[0]) + class __extend__(pairtype(InstanceRepr, InstanceRepr)): def convert_from_to((r_ins1, r_ins2), v, llops): Modified: pypy/dist/pypy/rpython/lltypesystem/rpbc.py ============================================================================== --- pypy/dist/pypy/rpython/lltypesystem/rpbc.py (original) +++ pypy/dist/pypy/rpython/lltypesystem/rpbc.py Fri May 5 00:36:20 2006 @@ -166,7 +166,11 @@ assert isinstance(s_instance, annmodel.SomeInstance) classdef = hop.s_result.classdef v_instance = rclass.rtype_new_instance(hop.rtyper, classdef, - hop.llops) + hop.llops, hop) + if isinstance(v_instance, tuple): + v_instance, must_call_init = v_instance + if not must_call_init: + return v_instance s_init = classdef.classdesc.s_read_attribute('__init__') v_init = Constant("init-func-dummy") # this value not really used else: Added: pypy/dist/pypy/rpython/lltypesystem/rtagged.py ============================================================================== --- (empty file) +++ pypy/dist/pypy/rpython/lltypesystem/rtagged.py Fri May 5 00:36:20 2006 @@ -0,0 +1,108 @@ +from pypy.objspace.flow.model import Constant +from pypy.rpython.rclass import getclassrepr, get_type_repr +from pypy.rpython.lltypesystem import lltype +from pypy.rpython.lltypesystem.rclass import InstanceRepr, CLASSTYPE +from pypy.rpython.lltypesystem.rclass import MissingRTypeAttribute +from pypy.rpython.lltypesystem.rclass import ll_issubclass_const +from pypy.rpython.rmodel import TyperError, inputconst + + +class TaggedInstanceRepr(InstanceRepr): + + def __init__(self, rtyper, classdef, unboxedclassdef): + InstanceRepr.__init__(self, rtyper, classdef) + self.unboxedclassdef = unboxedclassdef + self.is_parent = unboxedclassdef is not classdef + + def _setup_repr(self): + InstanceRepr._setup_repr(self) + if len(self.allinstancefields) != 1: + raise TyperError("%r cannot have fields besides __class__: %r" % ( + self.classdef, self.allinstancefields.keys())) + + def new_instance(self, llops, classcallhop=None): + if self.is_parent: + raise TyperError("don't instantiate %r, it is a parent of an " + "UnboxedValue class" % (self.classdef,)) + if classcallhop is None: + raise TyperError("must instantiate %r by calling the class" % ( + self.classdef,)) + hop = classcallhop + if not (hop.spaceop.opname == 'simple_call' and hop.nb_args == 2): + raise TyperError("must instantiate %r with a simple class call" % ( + self.classdef,)) + v_value = hop.inputarg(lltype.Signed, arg=1) + c_one = hop.inputconst(lltype.Signed, 1) + hop.exception_is_here() + v2 = hop.genop('int_lshift_ovf', [v_value, c_one], + resulttype = lltype.Signed) + v2p1 = hop.genop('int_add', [v2, c_one], + resulttype = lltype.Signed) + v_instance = hop.genop('cast_int_to_ptr', [v2p1], + resulttype = self.lowleveltype) + return v_instance, False # don't call __init__ + + def convert_const(self, value): + raise NotImplementedError + + def getfield(self, vinst, attr, llops, force_cast=False): + if attr != '__class__': + raise MissingRTypeAttribute(attr) + unboxedclass_repr = getclassrepr(self.rtyper, self.unboxedclassdef) + cunboxedcls = inputconst(CLASSTYPE, unboxedclass_repr.getvtable()) + if self.is_parent: + vinst = llops.genop('cast_pointer', [vinst], + resulttype=self.common_repr()) + return llops.gendirectcall(ll_unboxed_getclass, vinst, cunboxedcls) + else: + return cunboxedcls + + def rtype_type(self, hop): + raise NotImplementedError + + def rtype_setattr(self, hop): + raise NotImplementedError + + def ll_str(self, i): + raise NotImplementedError + + def rtype_isinstance(self, hop): + if not hop.args_s[1].is_constant(): + raise TyperError("isinstance() too complicated") + [classdesc] = hop.args_s[1].descriptions + classdef = classdesc.getuniqueclassdef() + + class_repr = get_type_repr(self.rtyper) + instance_repr = self.common_repr() + v_obj, v_cls = hop.inputargs(instance_repr, class_repr) + cls = v_cls.value + answer = self.unboxedclassdef.issubclass(classdef) + c_answer_if_unboxed = hop.inputconst(lltype.Bool, answer) + minid = hop.inputconst(lltype.Signed, cls.subclassrange_min) + maxid = hop.inputconst(lltype.Signed, cls.subclassrange_max) + return hop.gendirectcall(ll_unboxed_isinstance_const, v_obj, + minid, maxid, c_answer_if_unboxed) + + +def ll_unboxed_getclass(instance, class_if_unboxed): + if lltype.cast_ptr_to_int(instance) & 1: + return class_if_unboxed + else: + return instance.typeptr + +def ll_unboxed_isinstance_const(obj, minid, maxid, answer_if_unboxed): + if not obj: + return False + if lltype.cast_ptr_to_int(obj) & 1: + return answer_if_unboxed + else: + return ll_issubclass_const(obj.typeptr, minid, maxid) + +def rtype_getvalue_from_unboxed(hop): + assert isinstance(hop.args_r[0], TaggedInstanceRepr) + assert not hop.args_r[0].is_parent + [v_instance] = hop.inputargs(hop.args_r[0]) + v2 = hop.genop('cast_ptr_to_int', [v_instance], resulttype = lltype.Signed) + c_one = hop.inputconst(lltype.Signed, 1) + return hop.genop('int_rshift', [v2, c_one], resulttype = lltype.Signed) + Modified: pypy/dist/pypy/rpython/lltypesystem/test/test_lltype.py ============================================================================== --- pypy/dist/pypy/rpython/lltypesystem/test/test_lltype.py (original) +++ pypy/dist/pypy/rpython/lltypesystem/test/test_lltype.py Fri May 5 00:36:20 2006 @@ -617,3 +617,14 @@ a[0] = 34 assert s.y == 34 py.test.raises(IndexError, "a[1]") + +def test_odd_ints(): + T = GcStruct('T') + S = GcStruct('S', ('t', T)) + s = cast_int_to_ptr(Ptr(S), 21) + assert typeOf(s) == Ptr(S) + assert cast_ptr_to_int(s) == 21 + t = cast_pointer(Ptr(T), s) + assert typeOf(t) == Ptr(T) + assert cast_ptr_to_int(t) == 21 + assert s == cast_pointer(Ptr(S), t) Added: pypy/dist/pypy/rpython/lltypesystem/test/test_rtagged.py ============================================================================== --- (empty file) +++ pypy/dist/pypy/rpython/lltypesystem/test/test_rtagged.py Fri May 5 00:36:20 2006 @@ -0,0 +1,53 @@ +import sys +from pypy.rpython.test.test_llinterp import interpret +from pypy.rpython.lltypesystem import lltype +from pypy.rpython.objectmodel import UnboxedValue + + +class A(object): + pass +class B(A): + def __init__(self, normalint): + self.normalint = normalint +class C(A, UnboxedValue): + pass + +def test_on_top_of_cpython(): + assert C(17).getvalue() == 17 + +def test_instantiate(): + def fn1(n): + return C(n) + res = interpret(fn1, [42]) + value = lltype.cast_ptr_to_int(res) + assert value == 42 * 2 + 1 # for now + +def test_getvalue(): + def fn1(n): + return C(n).getvalue() + res = interpret(fn1, [42]) + assert res == 42 + +def test_overflowerror(): + def makeint(n): + try: + return C(n) + except OverflowError: # 'n' out of range + return B(n) + + def fn2(n): + x = makeint(n) + if isinstance(x, B): + return 'B', x.normalint + elif isinstance(x, C): + return 'C', x.getvalue() + else: + return 'A', 0 + + res = interpret(fn2, [-117]) + assert res.item0 == 'C' + assert res.item1 == -117 + + res = interpret(fn2, [sys.maxint]) + assert res.item0 == 'B' + assert res.item1 == sys.maxint Modified: pypy/dist/pypy/rpython/objectmodel.py ============================================================================== --- pypy/dist/pypy/rpython/objectmodel.py (original) +++ pypy/dist/pypy/rpython/objectmodel.py Fri May 5 00:36:20 2006 @@ -3,6 +3,8 @@ RPython-compliant way. """ +import sys, new + class Symbolic(object): def annotation(self): @@ -24,7 +26,6 @@ from pypy.rpython.lltypesystem import lltype return lltype.Signed -import new def instantiate(cls): "Create an empty instance of 'cls'." @@ -108,6 +109,31 @@ def hlinvoke(repr, llcallable, *args): raise TypeError, "hlinvoke is meant to be rtyped and not called direclty" + +class UnboxedValue(object): + """A mixin class to use for classes that have exactly one field which + is an integer. They are represented as a tagged pointer.""" + _mixin_ = True + + def __new__(cls, value): + assert '__init__' not in cls.__dict__ # won't be called anyway + int_as_pointer = value * 2 + 1 # XXX for now + if -sys.maxint-1 <= int_as_pointer <= sys.maxint: + result = super(UnboxedValue, cls).__new__(cls) + result._value_ = value + return result + else: + raise OverflowError("UnboxedValue: argument out of range") + + def __init__(self, value): + pass + + def getvalue(self): + return getvalue_from_unboxed(self) + +def getvalue_from_unboxed(obj): + return obj._value_ # this function is special-cased by the annotator + # ____________________________________________________________ Modified: pypy/dist/pypy/rpython/ootypesystem/rclass.py ============================================================================== --- pypy/dist/pypy/rpython/ootypesystem/rclass.py (original) +++ pypy/dist/pypy/rpython/ootypesystem/rclass.py Fri May 5 00:36:20 2006 @@ -392,7 +392,7 @@ def create_instance(self): return ootype.new(self.object_type) - def new_instance(self, llops): + def new_instance(self, llops, classcallhop=None): """Build a new instance, without calling __init__.""" classrepr = getclassrepr(self.rtyper, self.classdef) v_instance = llops.genop("new", @@ -424,6 +424,8 @@ llattrvalue = self.allfields[mangled].convert_const(attrvalue) setattr(result, mangled, llattrvalue) +buildinstancerepr = InstanceRepr + class __extend__(pairtype(InstanceRepr, InstanceRepr)): def convert_from_to((r_ins1, r_ins2), v, llops): Modified: pypy/dist/pypy/rpython/rbuiltin.py ============================================================================== --- pypy/dist/pypy/rpython/rbuiltin.py (original) +++ pypy/dist/pypy/rpython/rbuiltin.py Fri May 5 00:36:20 2006 @@ -376,9 +376,17 @@ def rtype_cast_ptr_to_int(hop): assert isinstance(hop.args_r[0], rptr.PtrRepr) vlist = hop.inputargs(hop.args_r[0]) + hop.exception_cannot_occur() return hop.genop('cast_ptr_to_int', vlist, resulttype = lltype.Signed) +def rtype_cast_int_to_ptr(hop): + assert hop.args_s[0].is_constant() + v_type, v_input = hop.inputargs(lltype.Void, lltype.Signed) + hop.exception_cannot_occur() + return hop.genop('cast_int_to_ptr', [v_input], + resulttype = hop.r_result.lowleveltype) + def rtype_runtime_type_info(hop): assert isinstance(hop.args_r[0], rptr.PtrRepr) vlist = hop.inputargs(hop.args_r[0]) @@ -392,6 +400,7 @@ BUILTIN_TYPER[lltype.direct_arrayitems] = rtype_direct_arrayitems BUILTIN_TYPER[lltype.direct_ptradd] = rtype_direct_ptradd BUILTIN_TYPER[lltype.cast_ptr_to_int] = rtype_cast_ptr_to_int +BUILTIN_TYPER[lltype.cast_int_to_ptr] = rtype_cast_int_to_ptr BUILTIN_TYPER[lltype.typeOf] = rtype_const_result BUILTIN_TYPER[lltype.nullptr] = rtype_const_result BUILTIN_TYPER[lltype.getRuntimeTypeInfo] = rtype_const_result Modified: pypy/dist/pypy/rpython/rclass.py ============================================================================== --- pypy/dist/pypy/rpython/rclass.py (original) +++ pypy/dist/pypy/rpython/rclass.py Fri May 5 00:36:20 2006 @@ -33,7 +33,7 @@ # # see getclassrepr() # result = getinstancerepr(rtyper, None, nogc=False) #else: - result = rtyper.type_system.rclass.InstanceRepr( + result = rtyper.type_system.rclass.buildinstancerepr( rtyper, classdef, does_need_gc=does_need_gc) rtyper.instance_reprs[classdef, does_need_gc] = result @@ -132,8 +132,8 @@ def _setup_repr_final(self): pass - def new_instance(self, llops): - pass + def new_instance(self, llops, classcallhop=None): + raise NotImplementedError def convert_const(self, value): if value is None: @@ -165,19 +165,19 @@ return result def rtype_type(self, hop): - pass + raise NotImplementedError def rtype_getattr(self, hop): - pass + raise NotImplementedError def rtype_setattr(self, hop): - pass + raise NotImplementedError def rtype_is_true(self, hop): - pass + raise NotImplementedError def ll_str(self, i): - pass + raise NotImplementedError def get_ll_eq_function(self): return None # defaults to compare by identity ('==' on pointers) @@ -187,9 +187,9 @@ # ____________________________________________________________ -def rtype_new_instance(rtyper, classdef, llops): +def rtype_new_instance(rtyper, classdef, llops, classcallhop=None): rinstance = getinstancerepr(rtyper, classdef) - return rinstance.new_instance(llops) + return rinstance.new_instance(llops, classcallhop) def instance_annotation_for_cls(rtyper, cls): try: 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 Fri May 5 00:36:20 2006 @@ -93,3 +93,19 @@ return A.flag res = interpret(f, [], policy=policy) assert res + +def test_odd_ints(): + T = GcStruct('T') + S = GcStruct('S', ('t', T)) + PT = Ptr(T) + PS = Ptr(S) + def fn(n): + s = cast_int_to_ptr(PS, n) + assert typeOf(s) == PS + assert cast_ptr_to_int(s) == n + t = cast_pointer(PT, s) + assert typeOf(t) == PT + assert cast_ptr_to_int(t) == n + assert s == cast_pointer(PS, t) + + interpret(fn, [11521]) From arigo at codespeak.net Fri May 5 00:45:06 2006 From: arigo at codespeak.net (arigo at codespeak.net) Date: Fri, 5 May 2006 00:45:06 +0200 (CEST) Subject: [pypy-svn] r26771 - pypy/dist/pypy/annotation Message-ID: <20060504224506.8333F1008F@code0.codespeak.net> Author: arigo Date: Fri May 5 00:45:05 2006 New Revision: 26771 Modified: pypy/dist/pypy/annotation/description.py Log: (pedronis, arigo) Don't specialize mixin methods too much. Modified: pypy/dist/pypy/annotation/description.py ============================================================================== --- pypy/dist/pypy/annotation/description.py (original) +++ pypy/dist/pypy/annotation/description.py Fri May 5 00:45:05 2006 @@ -355,7 +355,7 @@ # for debugging if not hasattr(value, 'class_'): value.class_ = self.pyobj # remember that this is really a method - if self.specialize or mixin: + if self.specialize: # make a custom funcdesc that specializes on its first # argument (i.e. 'self'). from pypy.annotation.specialize import specialize_argtype @@ -365,6 +365,12 @@ specializer=argtype0) self.classdict[name] = funcdesc continue + if mixin: + # make a new copy of the FunctionDesc for this class, + # but don't specialize further for all subclasses + funcdesc = FunctionDesc(self.bookkeeper, value) + self.classdict[name] = funcdesc + continue # NB. if value is, say, AssertionError.__init__, then we # should not use getdesc() on it. Never. The problem is # that the py lib has its own AssertionError.__init__ which From cfbolz at codespeak.net Fri May 5 01:12:23 2006 From: cfbolz at codespeak.net (cfbolz at codespeak.net) Date: Fri, 5 May 2006 01:12:23 +0200 (CEST) Subject: [pypy-svn] r26772 - in pypy/dist/pypy: interpreter module/_weakref/test Message-ID: <20060504231223.00CCB10089@code0.codespeak.net> Author: cfbolz Date: Fri May 5 01:12:17 2006 New Revision: 26772 Modified: pypy/dist/pypy/interpreter/typedef.py pypy/dist/pypy/module/_weakref/test/test_weakref.py Log: make sure that interplevel __del__ is called even in the presence of an applevel __del__. This prevents a (virtual, but should also work on pypy-c) segfault in py.py. Modified: pypy/dist/pypy/interpreter/typedef.py ============================================================================== --- pypy/dist/pypy/interpreter/typedef.py (original) +++ pypy/dist/pypy/interpreter/typedef.py Fri May 5 01:12:17 2006 @@ -77,6 +77,8 @@ except OperationError, e: e.write_unraisable(self.space, 'method __del__ of ', self) e.clear(self.space) # break up reference cycles + if hasattr(cls, '__del__'): + cls.__del__(self) elif wants_slots: supercls = get_unique_interplevel_subclass(cls, hasdict, False, False) Modified: pypy/dist/pypy/module/_weakref/test/test_weakref.py ============================================================================== --- pypy/dist/pypy/module/_weakref/test/test_weakref.py (original) +++ pypy/dist/pypy/module/_weakref/test/test_weakref.py Fri May 5 01:12:17 2006 @@ -144,6 +144,24 @@ w = _weakref.ref(A()) raises(TypeError, hash, w) + def test_weakref_subclass_with_del(self): + import _weakref + class Ref(_weakref.ref): + def __del__(self): + b.a = 42 + class A(object): + pass + a = A() + b = A() + b.a = 1 + w = Ref(a) + del w + assert b.a == 42 + if _weakref.getweakrefcount(a) > 0: + # the following can crash if the presence of the applevel __del__ + # leads to the fact that the __del__ of _weakref.ref is not called. + assert _weakref.getweakrefs(a)[0]() is a + class AppTestProxy(object): def setup_class(cls): space = gettestobjspace(usemodules=('_weakref',)) From arigo at codespeak.net Fri May 5 01:33:51 2006 From: arigo at codespeak.net (arigo at codespeak.net) Date: Fri, 5 May 2006 01:33:51 +0200 (CEST) Subject: [pypy-svn] r26773 - pypy/dist/pypy/interpreter Message-ID: <20060504233351.655AC10089@code0.codespeak.net> Author: arigo Date: Fri May 5 01:33:49 2006 New Revision: 26773 Modified: pypy/dist/pypy/interpreter/typedef.py Log: Make annotatable (probably). Modified: pypy/dist/pypy/interpreter/typedef.py ============================================================================== --- pypy/dist/pypy/interpreter/typedef.py (original) +++ pypy/dist/pypy/interpreter/typedef.py Fri May 5 01:33:49 2006 @@ -70,6 +70,7 @@ if wants_del: supercls = get_unique_interplevel_subclass(cls, hasdict, wants_slots, False) + parent_destructor = getattr(cls, '__del__', None) class Proto(object): def __del__(self): try: @@ -77,8 +78,8 @@ except OperationError, e: e.write_unraisable(self.space, 'method __del__ of ', self) e.clear(self.space) # break up reference cycles - if hasattr(cls, '__del__'): - cls.__del__(self) + if parent_destructor is not None: + parent_destructor(self) elif wants_slots: supercls = get_unique_interplevel_subclass(cls, hasdict, False, False) From bea at codespeak.net Fri May 5 02:13:14 2006 From: bea at codespeak.net (bea at codespeak.net) Date: Fri, 5 May 2006 02:13:14 +0200 (CEST) Subject: [pypy-svn] r26779 - pypy/extradoc/talk/agile2006 Message-ID: <20060505001314.9569A10089@code0.codespeak.net> Author: bea Date: Fri May 5 02:13:13 2006 New Revision: 26779 Modified: pypy/extradoc/talk/agile2006/draftpaper_agile2006.txt Log: review based on shepherd feedback - please review language and such..... Carl - pdf time again Modified: pypy/extradoc/talk/agile2006/draftpaper_agile2006.txt ============================================================================== --- pypy/extradoc/talk/agile2006/draftpaper_agile2006.txt (original) +++ pypy/extradoc/talk/agile2006/draftpaper_agile2006.txt Fri May 5 02:13:13 2006 @@ -1,11 +1,11 @@ =================================================================================== -Trouble in Paradise: Open Source projects, EU-funding and Agile practices +Trouble in Paradise: the Open Source project PyPy, EU-funding and Agile practices =================================================================================== .. sectnum .. raw:: latex - \author{Beatrice During} + \author{Beatrice During, Change Maker, bea at changemaker.nu} \begin{abstract} PyPy is an Open Source project, partly funded by the European Union, employing @@ -45,7 +45,7 @@ Today the project has over 4 years of intense activity as an Open Source community (F/OSS) effort and have completed a successful first year of the -EU-funded effort. In order to understand how the PyPy project managed and +EU-funded effort. In order to understand how the PyPy project manages to strike a balance between being an F/OSS community, while also having the core work of the project being funded by the European Union (with all the structure and process requirements that entails) we need to look at the @@ -55,7 +55,7 @@ - The F/OSS/Python community factor. Different Open Source communities have different "flavors" regarding culture, communication climate, structure, - decision-process etc. PyPy was born out of the Python Community and share + decision-process etc. PyPy was born out of the Python Community and shares some of its characteristics which have had a huge influence on the project process so far. Aspects such as distributed/dispersed development and the supporting practices and infrastructure in place to quality assure software @@ -63,7 +63,7 @@ factor. - The Agile factor. Almost a subset of the F/OSS/Python community factor - - agile practices that has been in use since the inception of the project, that + agile practices that have been in use since the inception of the project, that in fact have been the main drivers of the project are very much inspired by other projects in the Python community. A key aspect of this influencing factor is the Python version of "sprinting". We will present this "agile" @@ -128,6 +128,9 @@ Programming and abstract interpretation techniques. The methodology objective aims at showcasing the "sprint-driven development method" being used by PyPy and you can view this paper as part of fulfilling the methodology objective. +See also a paper on the sprint method submitted to the XP 2006 conference titled +"Sprint-Driven Development: Agile methodologies in a Distributed Open Source +Project (PyPy)". Strategy: +++++++++ @@ -136,9 +139,6 @@ through an open and transparent communication and working style. The challenge has been to implement this strategy, not only in the F/OSS community part of the project, but also in the partially funded consortium structure of the project. -The structure of the project and the consortium needed to adhere to this -strategy while also conforming to the actual requirements of the 6th Framework -Programme. The F/OSS part of PyPy has no budget tied to it and no formal organizational structure. There are no resources tied to it other than the volunteers @@ -200,7 +200,7 @@ parties involved had to adapt to the situation. The contract with the EU was signed and the funded part of the project, with -it?s consortium structure, started 1 of December 2004. The funded part of the +its consortium structure, started 1 of December 2004. The funded part of the project ends in November 2006. The first funded year of the project ended with a review in Brussels in January @@ -224,8 +224,7 @@ language implementations as separate projects which communicate and discuss their experiences and approaches with each other. This intra-extra community focus and interest has created a collaborative atmosphere with an open and -transparent communication climate. The key to a lively and working community is -the people factor, as always, and of course so for the Python community as well. +transparent communication climate. The PyPy community ------------------ @@ -238,12 +237,12 @@ factor. Thus making it easier recruit people into the PyPy community. The PyPy project inherited the focus on collaborative approaches and open -communication climate. The nature of using sprints as a core technique as a -way to kick-start the project as well as moving the sprints to different -locations as a strategy to encourage participation by meeting people locally -are clear examples of this. During the period of 2003-2004 6 sprints were -arranged in various European cities, hosted by universities and private -persons, participation funded privately. The effect on the evolving community +communication climate. The strategy of using sprints, as a core technique, to +kick-start the project as well as moving the sprints to different +locations had clear effects.It encouraged participation by meeting people locally. +During the period of 2003-2004 6 sprints were arranged in various European cities. +These sprints were hosted by universities and private +individuals, participation was funded privately. The effect on the evolving community was a stable subscriber participation on the development list of between 140-150 people. After the EU-funding and the more systematic structure of sprinting every 6th week the amount of subscribers went from around 150 people to @@ -265,27 +264,31 @@ users of a separate F/OSS project called the py.test, tools for automated testing with PyPy developers contributing improvements to py.test. Py.test contains a sophisticated system for running tests against the Python Standard -Library, with automatic selection of overriding tests in case there is -internally developed code that overrides the Python Standard Library - -important compliance features when the project is about language -implementation. There are also powerful mechanisms for disabling specific +Library. It provides automatic selection of overriding tests in case there is +internally developed code that overrides the Python Standard Library. These are +important compliance features when the project is about language implementation. +There are also powerful mechanisms for disabling specific tests and for producing useful traceback output. There are also automatically generated web pages that show the status of all tests as per the latest checked -in test results. +in test results. This together with a public issue-tracker covering bugs keeps the +development group focused on the quality of the code when doing +continous integration. It greatly reduces the need +to coordinate and delegate refactoring work - this is handled in a self-organized way. The main communication channels between developers involved in PyPy is to discuss over IRC (Internet-Relay-Chat) - open for all who are interested. Several mailing lists for discussions and information are also used. Web pages, documentation, tutorials, talks and papers etc are all available on the central developer server for everyone to access. A very useful feature that really supports -information and communication (the author can attest to this from her own -experience) are the public email archives covering the key mailing lists - going -back to the start of 2003. - -An extensive coding guide, published on codespeak.net (development website) -serves as an introduction to the set of specifications being used while coding -PyPy. The coding guide covers not only naming conventions but also design, -test and documentation guidelines. +information and communication are the public email archives covering the key +mailing lists - going back to the start of 2003. As a newcomer to the project +in the fall of 2003 these public and easily accessable mailing list archives +was the primary means for me personally to get into the project. It provided answers +to who had been key people in the process, what had been crucial topics, how had +discussions and decisions been handled. It is also regularly being used with newcomers +in the development team, providing fast answers to questions and also providing context +to technical decisions being made in the past. A useful just-in-time documentation +and a unorthodox but very efficient way of disseminating information and knowledge. Now - all this infrastructure is being used in almost all larger open source projects and quite a few of them are much more hierarchical and non-transparent @@ -298,18 +301,30 @@ strong automated tools covering tests, versions and back ups covering the technical level. +An extensive coding guide, published on codespeak.net (development website) +serves as an introduction to the set of specifications being used while coding +PyPy. Yet another piece of the puzzle, the coding guide together with +commit-access to both source code and tests supports cohesion in the development +process. This increases readability and uniformity so that automated testing tools can +be more efficiently used. Again - simple and useful support that is much needed when +working dispersed in a larger team of developers that might never meet face to face. + In a distributed and dispersed work style these two (social and technical) levels needs to be consistent and support each other. Discrepancies would be immediately noticed. As stated before - the people factor is again evident. If you wish to encourage participation and contribution there has to be trust as well as a supportive environment in order to manage a virtual collaborative -workspace. +workspace. The main feature of such a supportive infrastructure is to reduce +the cost of information since coordination and communication is even more difficult +in a dispersed environment. If this easily accessed information of the status of the software +is combined with trust (that is commit-rights) you have the basis for a proactive, +self-organized culture. Supporting practices -------------------- Another good example of the collaborative nature of the Python community is the -way which the various projects share best practices. Core developers in the +way in which the various projects share best practices. Core developers in the PyPy project picked up the practice of synchronization meetings as a powerful way of supporting distributed and dispersed development. This practice was inspired by the experiences of development processes at Canonical. @@ -325,8 +340,40 @@ Sync-meetings have proved to be a very good complement to a process in which the project sprints every 6th week. Sync-meetings keep cohesion as well as a -team focus-and-feel for the dispersed work style between sprints. - +team focus-and-feel for the dispersed work style between sprints. There are three +crucial aspects of this practice. The first one is that our experience as well as +that of Canonical points to keeping the time for the meeting brief. The reason for +30 minutes limit is that it forces prioritization on what topics to choose. However +complex your development situation is you should choose not more than 3 topics, +topics that could be discussed and decided upon during these 30 minutes. Not having +this timelimit would create long and tiresome IRC meetings which would demotivate +people and also create more confusion than results. + +The second aspect is that it has a fixed format in which the meeting starts with +all developers participating in the meeting presents a very short status - answering +the questions LAST (last week), NEXT (their focus for the upcoming week) +and BLOCKERS (if they are stuck and need help). This means that the group get +overview and can track progress, albeit loosely. All individuals get an opportunity to +voice their personal situation and the group jointly discuss potential blockers and how +to solve them. The fixed format help to keep focus and creates a rythm that makes it +easier for newcomers to get into the flow of the meeting. + +The third aspect is also the main challenge with the practice. In PyPy we rotate +the organization of the meetings between the developers. But because meeting +moderation has to do with experience, people skills as well as a certain overview of +the project not everyone can actually do this task. Our experience shows that it is +also very important to have core people involved in identifying topics needing to be +discussed - having the progress of the project in mind. It is very easy to choose +topics that do not need the group mind to discuss, that are too detailed, that has +too much focus on information distribution rather than discussions. + +Here is what one of the new core developers of PyPy says about sync-meetings: + +"Sync-meetings are useful because they enable developers to discuss and clarify issues +among themselves and to provide a common focus when working distributedly. They +are also a lightweight way to syncronize activities, resolve blockers and to get an +overview about who is currently doing what work." + Influencing factors: agile practices in PyPy ============================================ @@ -359,15 +406,26 @@ with the core developers. - It is a live training session not only in producing code but also in the - development methods being used (TDD, pair programming etc, the sprint method - in itself). + development methods being used (the sprint method in itself, pair programming + and TDD). - It supports activities such as design decisions and high-level requirements discussions, creating cohesion and understanding as well as minimizing risks with dispersed/distributed work where these kind of activities can be really difficult to manage. + +In order to provide examples - in PyPy these discussion sessions have been done in +various different ways during sprints. The proposal for the EU and the work package +descriptions were drafted through group discussions during sprints. Later sprints in which +the process needed design decisions, developers paired up in several groups of 2-4 +people per group for daily discussion sessions. These sessions ended with brief +documentation and presentations for the other groups where decisions were made. +Usually what happens is that the daily sprint planning results in a pair of core developers +choosing a topic to discuss. These discussions have even acted as tutorials for other +developers sitting in and following the discussions. Some of these discussions have also +been filmed for dissemination purposes. -The reason for naming the method sprinting, not at all connected to Scrum and +The reason for naming the method sprinting, is not at all connected to Scrum and the usage of sprints in that context, according to Tres Seaver is: *"... because of the fact that we weren't doing XP in its proper sense, @@ -447,11 +505,15 @@ management team the strategy implemented was to delegate as much as possible of the responsibilities and decision-making to the core developers. -The strategy was to keep "conceptual integrity" (Brooks) of the vision and the -idea in the hands of the core developers. A somewhat negative result was the -added workload and responsibility on developers regarding EU related work. The -core developers were organized into a technical board, responsible for planning -and coordinating the development work between the partners. +The strategy was to keep "conceptual integrity" [1] of the vision and the +idea in the hands of the core developers. As Brooks stresses, a uniform system +design is better than uncoordinated and independent design ideas. The core developers +had a clear and agreed vision - but would they be allowed to implement it within a +fixed contract workstyle, with new partners involved that had not been involved in +the process from the start? The core developers were organized into a technical +board, responsible for planning and coordinating the development work between +the partners, with the mandate to make decisions. A somewhat negative result +was the added workload and responsibility on developers regarding EU related work. This structure was the most difficult to design and implement due to the very different nature of its purpose compared to the collaborative, self-organized @@ -467,36 +529,6 @@ time plan, deliverables and work package descriptions on a high-level, not broken down into more granular tasks. -Resource tracking and reporting -------------------------------- - -The nature of reporting on a consortium level is very much focused on the costs -incurred by each partner compared to budget, by the consortium on a specific -work package and of the consortium overall. The consortium is free to reallocate -budgeted man month funding between partners during the project. The project -reports costs per period, PyPy has two periods. - -Again - the need for open and transparent communication together with a -collaborative climate created the need to have what we believe a unique view on -cost reporting within the project. In PyPy all time sheets are gathered on a -monthly basis and stored in central repository, accessible for all consortium -partners (managers and developers alike). Cost claims from all partners are -gathered on a six month basis. This data helps the management board and -technical board to assess the status of work. - -Templates for time sheets, costs claims, resource tracking tools etc are created -in open formats and all data is stored under the same version control that we -use for the source code. All reports are produced with docutils/ReST format -which together with automated mailing lists for covering updates in the version -control repositories allows for collaborate peer-reviewing regarding the -EU-level of reports. Again the strategy was to use the same tools and practices -on consortium level work as is used in the development process. Interesting to -note is that the technical reports written for the Commission regarding certain -deliverables and progress have also been a great help towards the community who -also has free access to these reports and view them as extra, although -peculiarly formated, documentation. - - Communication and documentation ------------------------------- @@ -594,7 +626,7 @@ risk and complexity would be if the consortium level would "shut the door" on the community, enforcing a more closed development process. -As in many cases - being risk aware is the first step to mitigate. Because the +As in many cases - being risk aware is the first step to mitigation. Because the project is so deeply rooted in the F/OSS Python community, with its specific culture and climate, and because so many people involved in the core work on both the development and consortium level also shared this background they took @@ -620,39 +652,65 @@ We believe so. The one clear dominating factor to make all this succeed is, as always, the people factor, the CRACK performers as Boehm and Turner calls them -("Collaborative, Representative, Authorized, Committed, Knowledgeable"). - +("Collaborative, Representative, Authorized, Committed, Knowledgeable"). [2] The core developers of the PyPy project had the right mix of various skills in order to succeed in setting up a hybrid environment - enabling them to work full time on a project they strongly believed in. The most crucial mix of skills for making this possible was/are: -- social (the ability to communicate, "manage" groups and handle conflicts) - -- leadership abilities (both on technical levels as well on general social - levels) - -- ability to network (to find and invite actors in the various cultures) - -- entrepreneurs (to instigate the idea of EU-funding and also to create - consortium and companies) - -- curious and collaborative (towards other Python implementations and other - languages and research approaches) - -- technical skills (programming language and implementation aspects, - frameworks, mathematics, computer science etc) - -- ability to balance "conceptual integrity" (Brooks) with open and transparent - communication through sprints, documentation, tutorials, mentoring, - sync-meetings, thus also increasing the group of the core developers during - the project +- Social +The ability to communicate open and transparent, to mentor and tutor dispersed +as well as reinventing different collaborative workstyles of the sprint method, +"manage" groups and community as well as consortium, and handle conflicts) + +- Leadership abilities +The ability to step into formal leadership roles in technical board structures, manage +sprints and sync-meetings as well as the more informal management of the community +of developers. Managing the balance between encouraging participation but still holding +true to their vision, their "conceptual integrity". + +- Ability to network +To be open to other communities, inviting new partners in order to create a working +consortium structure in the EU-project, curious and collaborative towards other Python +implementations and other languages and research approaches, sharing knowledge and +experiences and seeking bets practices of other projects. + +- Entrepreneurs +To risk the community through pursuing the idea of EU-funding in order to fullfill the +ambitious vision, managing to not only create a consortium with innovative +structures of cooperation but also to create new companies. + +- Technical skills +Programming language and implementation aspects,frameworks, mathematics, computer +science - core skills for the project. Also the ability to design, setup and effectively manage +supporting infrastructure for the development process. + +- Managing the balance between encouraging participation but still holding +true to their vision, their "conceptual integrity" +This while working agile with open and transparent communication through sprints, +documentation, tutorials, mentoring, sync-meetings. Resulting in a lively and growing +the F/OSS community around the project. Drawing from these different skills within the community of developers in the PyPy project one possible conclusion would be that a truly agile approach dominating the work style of an Open Source project will increase the ability of -the community to spread the strategy of agility to other domains such as -entrepreneurship and business models (whether this is done by separate -individuals, subgroups or the whole group). By doing this hybrid projects such -as PyPy and others (Zope Europe among others) are made possible. +the community to spread the strategy of agility to other domains. +By this we mean that what started as agile practices in the development process +quickly became influencing factors when designing other project processes. Examples of +this in PyPy is how the sprint-driven development acts as a focal point not just for the +development work (co-located as well as dispersed) but also for the formal and informal +management of the project. Sprints together with the CRACK performers was what made +the community grow and evolve. It was the foundation for a hybrid project where agile +practices and EU-funding can fit within a distributed Open Source context. + + +References: +========== + +[1] Fredrick P. Brooks, Jr, "The mythical man-month, anniversary edition", +Addison-Wesley, 1995 + +[2] Barry Boehm,Richard Turner, "Observations on Balancing Discipline and Agility", +(drawn from the book "Balancing Agility and Discipline: A Guide to the Perplexed", +Addison Wesley, 2003) \ No newline at end of file From cfbolz at codespeak.net Fri May 5 02:47:36 2006 From: cfbolz at codespeak.net (cfbolz at codespeak.net) Date: Fri, 5 May 2006 02:47:36 +0200 (CEST) Subject: [pypy-svn] r26780 - in pypy/dist/pypy: doc/tool interpreter module/_weakref module/_weakref/test objspace/std objspace/std/test Message-ID: <20060505004736.9F5B510089@code0.codespeak.net> Author: cfbolz Date: Fri May 5 02:47:35 2006 New Revision: 26780 Modified: pypy/dist/pypy/doc/tool/makecontributor.py pypy/dist/pypy/interpreter/baseobjspace.py pypy/dist/pypy/interpreter/typedef.py pypy/dist/pypy/module/_weakref/interp__weakref.py pypy/dist/pypy/module/_weakref/test/test_weakref.py pypy/dist/pypy/objspace/std/objspace.py pypy/dist/pypy/objspace/std/test/test_typeobject.py pypy/dist/pypy/objspace/std/typeobject.py Log: don't add the field needed for weakref to all objects. Add support for the __weakref__ descriptor. Modified: pypy/dist/pypy/doc/tool/makecontributor.py ============================================================================== --- pypy/dist/pypy/doc/tool/makecontributor.py (original) +++ pypy/dist/pypy/doc/tool/makecontributor.py Fri May 5 02:47:35 2006 @@ -26,9 +26,8 @@ import uconf # http://codespeak.net/svn/uconf/dist/uconf for author, count in items: - user = uconf.system.User(author) - realname = user.realname - email = user.email + #user = uconf.system.User(author) + #realname = user.realname #print "%5d" % count, " ", realname, "<%s>" % email - print " ", realname, "<%s>" % email + print count, " ", author Modified: pypy/dist/pypy/interpreter/baseobjspace.py ============================================================================== --- pypy/dist/pypy/interpreter/baseobjspace.py (original) +++ pypy/dist/pypy/interpreter/baseobjspace.py Fri May 5 02:47:35 2006 @@ -7,7 +7,8 @@ from pypy.rpython.rarithmetic import r_uint, intmask import os -__all__ = ['ObjSpace', 'OperationError', 'Wrappable', 'W_Root'] +__all__ = ['ObjSpace', 'OperationError', 'Wrappable', 'W_Root', + 'WeakrefableMixin'] class W_Root(object): @@ -61,13 +62,32 @@ def identity_hash(self, space): return space.wrap(intmask(hash(self))) #space.id(self) + # used by _weakref implemenation + + def getweakref(self): + return None + + def setweakref(self, space, weakreflifeline): + typename = space.type(self).getname(space, '?') + raise OperationError(space.w_TypeError, space.wrap( + "cannot create weak reference to '%s' object" % typename)) + class Wrappable(W_Root): """A subclass of Wrappable is an internal, interpreter-level class that can nevertheless be exposed at application-level by space.wrap().""" def __spacebind__(self, space): return self +class WeakrefableMixin(object): + _mixin_ = True + __lifeline__ = None + + def getweakref(self): + return self.__lifeline__ + def setweakref(self, space, weakreflifeline): + self.__lifeline__ = weakreflifeline + class InternalSpaceCache(Cache): """A generic cache for an object space. Arbitrary information can be attached to the space by defining a function or class 'f' which Modified: pypy/dist/pypy/interpreter/typedef.py ============================================================================== --- pypy/dist/pypy/interpreter/typedef.py (original) +++ pypy/dist/pypy/interpreter/typedef.py Fri May 5 02:47:35 2006 @@ -5,7 +5,7 @@ import py from pypy.interpreter.gateway import interp2app from pypy.interpreter.argument import Arguments -from pypy.interpreter.baseobjspace import Wrappable, W_Root, ObjSpace +from pypy.interpreter.baseobjspace import Wrappable, W_Root, ObjSpace, WeakrefableMixin from pypy.interpreter.error import OperationError from pypy.tool.sourcetools import compile2 from pypy.rpython.objectmodel import instantiate @@ -36,26 +36,25 @@ return True -def get_unique_interplevel_subclass(cls, hasdict, wants_slots, needsdel=False): - key = cls, hasdict, wants_slots, needsdel +def get_unique_interplevel_subclass(cls, hasdict, wants_slots, needsdel=False, + weakrefable=False): + weakrefable = weakrefable and not issubclass(cls, WeakrefableMixin) + key = cls, hasdict, wants_slots, needsdel, weakrefable try: return _subclass_cache[key] except KeyError: - name = hasdict and "WithDict" or "NoDict" - name += wants_slots and "WithSlots" or "NoSlots" - name += needsdel and "WithDel" or "NoDel" - subcls = _buildusercls(cls, hasdict, wants_slots, needsdel) + subcls = _buildusercls(cls, hasdict, wants_slots, needsdel, weakrefable) _subclass_cache[key] = subcls return subcls get_unique_interplevel_subclass._annspecialcase_ = "specialize:memo" _subclass_cache = {} -def _buildusercls(cls, hasdict, wants_slots, wants_del): +def _buildusercls(cls, hasdict, wants_slots, wants_del, weakrefable): "NOT_RPYTHON: initialization-time only" typedef = cls.typedef if hasdict and typedef.hasdict: - return get_unique_interplevel_subclass(cls, False, wants_slots, wants_del) + return get_unique_interplevel_subclass(cls, False, wants_slots, wants_del, weakrefable) name = ['User'] if not hasdict: @@ -64,12 +63,15 @@ name.append('WithSlots') if wants_del: name.append('WithDel') + if weakrefable: + name.append('Weakrefable') + name.append(cls.__name__) name = ''.join(name) - if wants_del: - supercls = get_unique_interplevel_subclass(cls, hasdict, wants_slots, False) + supercls = get_unique_interplevel_subclass(cls, hasdict, wants_slots, + False, False) parent_destructor = getattr(cls, '__del__', None) class Proto(object): def __del__(self): @@ -81,7 +83,7 @@ if parent_destructor is not None: parent_destructor(self) elif wants_slots: - supercls = get_unique_interplevel_subclass(cls, hasdict, False, False) + supercls = get_unique_interplevel_subclass(cls, hasdict, False, False, False) class Proto(object): def user_setup_slots(self, nslots): @@ -93,7 +95,7 @@ def getslotvalue(self, index): return self.slots_w[index] elif hasdict: - supercls = get_unique_interplevel_subclass(cls, False, False, False) + supercls = get_unique_interplevel_subclass(cls, False, False, False, False) class Proto(object): def getdict(self): @@ -135,7 +137,10 @@ for key, value in Proto.__dict__.items() if not key.startswith('_') or key == '__del__']) - subcls = type(name, (supercls,), body) + if weakrefable and not issubclass(supercls, WeakrefableMixin): + subcls = type(name, (WeakrefableMixin, supercls), body) + else: + subcls = type(name, (supercls,), body) return subcls @@ -374,6 +379,12 @@ def descr_set_dict(space, w_obj, w_dict): w_obj.setdict(space, w_dict) +def descr_get_weakref(space, w_obj): + lifeline = w_obj.getweakref() + if lifeline is None: + return space.w_None + return lifeline.get_any_weakref(space) + def generic_ne(space, w_obj1, w_obj2): if space.eq_w(w_obj1, w_obj2): return space.w_False @@ -400,6 +411,10 @@ w_docstring = space.wrap(code.getdocstring()) return space.newtuple([w_docstring]) +weakref_descr = GetSetProperty(descr_get_weakref) +weakref_descr.name = '__weakref__' + + Code.typedef = TypeDef('internal-code', co_name = interp_attrproperty('co_name', cls=Code), co_varnames = GetSetProperty(fget_co_varnames, cls=Code), Modified: pypy/dist/pypy/module/_weakref/interp__weakref.py ============================================================================== --- pypy/dist/pypy/module/_weakref/interp__weakref.py (original) +++ pypy/dist/pypy/module/_weakref/interp__weakref.py Fri May 5 02:47:35 2006 @@ -7,9 +7,6 @@ from pypy.rpython.objectmodel import cast_address_to_object, cast_object_to_address from pypy.rpython.lltypesystem.llmemory import NULL -W_Weakrefable = W_Root -W_Weakrefable.__lifeline__ = None - class WeakrefLifeline(object): def __init__(self): @@ -67,6 +64,18 @@ if self.cached_weakref_index == index: self.cached_weakref_index = -1 + def get_any_weakref(self, space): + if self.cached_weakref_index != -1: + return cast_address_to_object( + self.addr_refs[self.cached_weakref_index], W_WeakrefBase) + w_weakreftype = space.gettypeobject(W_Weakref.typedef) + for i in range(len(self.addr_refs)): + addr = self.addr_refs[i] + if addr != NULL: + w_ref = cast_address_to_object(addr, W_WeakrefBase) + if space.is_true(space.isinstance(w_ref, w_weakreftype)): + return w_ref + return space.w_None class W_WeakrefBase(Wrappable): def __init__(w_self, space, lifeline, index, w_obj, w_callable): @@ -79,7 +88,7 @@ def dereference(self): if self.address == NULL: return self.space.w_None - return cast_address_to_object(self.address, W_Weakrefable) + return cast_address_to_object(self.address, W_Root) def invalidate(w_self): w_self.address = NULL @@ -113,10 +122,11 @@ return self.w_hash def descr__new__weakref(space, w_subtype, w_obj, w_callable=None): - assert isinstance(w_obj, W_Weakrefable) - if w_obj.__lifeline__ is None: - w_obj.__lifeline__ = WeakrefLifeline() - return w_obj.__lifeline__.get_weakref(space, w_subtype, w_obj, w_callable) + lifeline = w_obj.getweakref() + if lifeline is None: + lifeline = WeakrefLifeline() + w_obj.setweakref(space, lifeline) + return lifeline.get_weakref(space, w_subtype, w_obj, w_callable) def descr__eq__(space, ref1, ref2): if ref1.address == NULL or ref2.address == NULL: @@ -138,12 +148,10 @@ def getweakrefcount(space, w_obj): - if not isinstance(w_obj, W_Weakrefable): - return space.wrap(0) - if w_obj.__lifeline__ is None: + lifeline = w_obj.getweakref() + if lifeline is None: return space.wrap(0) else: - lifeline = w_obj.__lifeline__ result = 0 for i in range(len(lifeline.addr_refs)): if lifeline.addr_refs[i] != NULL: @@ -151,12 +159,10 @@ return space.wrap(result) def getweakrefs(space, w_obj): - if not isinstance(w_obj, W_Weakrefable): - return space.newlist([]) - if w_obj.__lifeline__ is None: + lifeline = w_obj.getweakref() + if lifeline is None: return space.newlist([]) else: - lifeline = w_obj.__lifeline__ result = [] for i in range(len(lifeline.addr_refs)): addr = lifeline.addr_refs[i] @@ -178,10 +184,11 @@ return space.call_args(w_obj, __args__) def proxy(space, w_obj, w_callable=None): - assert isinstance(w_obj, W_Weakrefable) - if w_obj.__lifeline__ is None: - w_obj.__lifeline__ = WeakrefLifeline() - return w_obj.__lifeline__.get_proxy(space, w_obj, w_callable) + lifeline = w_obj.getweakref() + if lifeline is None: + lifeline = WeakrefLifeline() + w_obj.setweakref(space, lifeline) + return lifeline.get_proxy(space, w_obj, w_callable) def descr__new__proxy(space, w_subtype, w_obj, w_callable=None): raise OperationError( Modified: pypy/dist/pypy/module/_weakref/test/test_weakref.py ============================================================================== --- pypy/dist/pypy/module/_weakref/test/test_weakref.py (original) +++ pypy/dist/pypy/module/_weakref/test/test_weakref.py Fri May 5 02:47:35 2006 @@ -13,6 +13,7 @@ assert _weakref.getweakrefcount(a) == 0 ref = _weakref.ref(a) assert ref() is a + assert a.__weakref__ is ref assert _weakref.getweakrefcount(a) == 1 del a assert ref() is None @@ -144,6 +145,78 @@ w = _weakref.ref(A()) raises(TypeError, hash, w) + def test_weakref_subclassing(self): + import _weakref + class A(object): + pass + class Ref(_weakref.ref): + pass + def callable(ref): + b.a = 42 + a = A() + b = A() + b.a = 1 + w = Ref(a, callable) + assert a.__weakref__ is w + assert b.__weakref__ is None + w1 = _weakref.ref(a) + w2 = _weakref.ref(a, callable) + assert a.__weakref__ is w1 + del a + assert w1() is None + assert w() is None + assert w2() is None + assert b.a == 42 + + def test_function_weakrefable(self): + skip("wip") + import _weakref + def f(x): + return 42 + wf = _weakref.ref(f) + assert wf()() == 42 + del f + assert wf() is None + + def test_method_weakrefable(self): + skip("wip") + import _weakref + class A(object): + def f(self): + return 42 + a = A() + w_unbound = _weakref.ref(A.f) + assert w_unbound()(A()) == 42 + w_bound = _weakref.ref(A().f) + assert w_bound()() == 42 + del A + assert w_unbound() is None + assert w_bound() is None + + def test_set_weakrefable(self): + skip("wip") + import _weakref + s = set([1, 2, 3, 4]) + w = _weakref.ref(s) + assert w() is s + del s + assert w() is None + + def test_generator_weakrefable(self): + skip("wip") + import _weakref + def f(x): + for i in range(x): + yield x + g = f(10) + w = _weakref.ref(g) + r = w().next() + assert r == 0 + r = g.next() + assert r == 1 + del g + assert w() is None + def test_weakref_subclass_with_del(self): import _weakref class Ref(_weakref.ref): Modified: pypy/dist/pypy/objspace/std/objspace.py ============================================================================== --- pypy/dist/pypy/objspace/std/objspace.py (original) +++ pypy/dist/pypy/objspace/std/objspace.py Fri May 5 02:47:35 2006 @@ -417,7 +417,7 @@ instance = instantiate(cls) else: w_subtype = w_type.check_user_subclass(w_subtype) - subcls = get_unique_interplevel_subclass(cls, w_subtype.hasdict, w_subtype.nslots != 0, w_subtype.needsdel) + subcls = get_unique_interplevel_subclass(cls, w_subtype.hasdict, w_subtype.nslots != 0, w_subtype.needsdel, w_subtype.weakrefable) instance = instantiate(subcls) instance.user_setup(self, w_subtype, w_subtype.nslots) assert isinstance(instance, cls) Modified: pypy/dist/pypy/objspace/std/test/test_typeobject.py ============================================================================== --- pypy/dist/pypy/objspace/std/test/test_typeobject.py (original) +++ pypy/dist/pypy/objspace/std/test/test_typeobject.py Fri May 5 02:47:35 2006 @@ -321,7 +321,7 @@ class C: __metaclass__ = T assert d - assert sorted(d[0].keys()) == ['__dict__','__doc__','__metaclass__','__module__'] + assert sorted(d[0].keys()) == ['__dict__','__doc__','__metaclass__','__module__', '__weakref__'] d = [] class T(type): def mro(cls): Modified: pypy/dist/pypy/objspace/std/typeobject.py ============================================================================== --- pypy/dist/pypy/objspace/std/typeobject.py (original) +++ pypy/dist/pypy/objspace/std/typeobject.py Fri May 5 02:47:35 2006 @@ -2,6 +2,7 @@ from pypy.interpreter.function import Function, StaticMethod from pypy.interpreter.argument import Arguments from pypy.interpreter import gateway +from pypy.interpreter.typedef import WeakrefableMixin, weakref_descr from pypy.objspace.std.stdtypedef import std_dict_descr, issubtypedef, Member from pypy.objspace.std.objecttype import object_typedef from pypy.objspace.std.dictproxyobject import W_DictProxyObject @@ -37,7 +38,7 @@ return "_%s%s" % (klass, name) -class W_TypeObject(W_Object): +class W_TypeObject(WeakrefableMixin, W_Object): from pypy.objspace.std.typetype import type_typedef as typedef lazyloaders = {} # can be overridden by specific instances @@ -51,6 +52,7 @@ w_self.ensure_static__new__() w_self.nslots = 0 w_self.needsdel = False + w_self.weakrefable = False w_self.w_bestbase = None # make sure there is a __doc__ in dict_w @@ -121,6 +123,7 @@ "multiple inheritance")) w_self.hasdict = w_self.hasdict or w_base.hasdict w_self.needsdel = w_self.needsdel or w_base.needsdel + w_self.weakrefable = w_self.weakrefable or w_base.weakrefable if not w_newstyle: # only classic bases raise OperationError(space.w_TypeError, space.wrap("a new-style class can't have only classic bases")) @@ -135,8 +138,10 @@ w_self.w_bestbase = w_newstyle wantdict = True + wantweakref = True if '__slots__' in dict_w: wantdict = False + wantweakref = False w_slots = dict_w['__slots__'] if space.is_true(space.isinstance(w_slots, space.w_str)): @@ -165,6 +170,12 @@ raise OperationError(space.w_TypeError, space.wrap("__dict__ slot disallowed: we already got one")) wantdict = True + elif slot_name == '__weakref__': + if w_self.weakrefable: + raise OperationError(space.w_TypeError, + space.wrap("__weakref__ slot disallowed: we already got one")) + + wantweakref = True else: # create member slot_name = _mangle(slot_name, name) @@ -182,6 +193,9 @@ w_self.hasdict = True if '__del__' in dict_w: w_self.needsdel = True + if wantweakref and not w_self.weakrefable: + w_self.dict_w['__weakref__'] = space.wrap(weakref_descr) + w_self.weakrefable = True w_type = space.type(w_self) if not space.is_w(w_type, space.w_type): w_self.mro_w = [] From ale at codespeak.net Fri May 5 10:05:20 2006 From: ale at codespeak.net (ale at codespeak.net) Date: Fri, 5 May 2006 10:05:20 +0200 (CEST) Subject: [pypy-svn] r26791 - in pypy/dist/pypy/lib/pyontology: . test Message-ID: <20060505080520.C5DBA10088@code0.codespeak.net> Author: ale Date: Fri May 5 10:05:19 2006 New Revision: 26791 Added: pypy/dist/pypy/lib/pyontology/constraint_classes.py Modified: pypy/dist/pypy/lib/pyontology/pyontology.py pypy/dist/pypy/lib/pyontology/test/test_ontology.py Log: Split files into to. some whitespace cleanup Added: pypy/dist/pypy/lib/pyontology/constraint_classes.py ============================================================================== --- (empty file) +++ pypy/dist/pypy/lib/pyontology/constraint_classes.py Fri May 5 10:05:19 2006 @@ -0,0 +1,495 @@ +from logilab.constraint.propagation import AbstractDomain, AbstractConstraint, ConsistencyFailure + +class OwlConstraint(AbstractConstraint): + + cost = 1 + + def __init__(self, variable): + AbstractConstraint.__init__(self, [variable]) + self.variable = variable + + def __repr__(self): + return '<%s %s>' % (self.__class__.__name__, str(self._variables[0])) + + def estimateCost(self, domains): + return self.cost + +def get_cardinality(props, cls): + if props.get(cls): + card = len(props[cls]) + elif props.get(None): + card = len(props[None]) + else: + card = 0 + return card + +class MaxCardinality(AbstractConstraint): + """Contraint: all values must be distinct""" + + def __init__(self, variable, cardinality): + AbstractConstraint.__init__(self, [variable]) + self.cost = 80 + self.variable = variable + self.cardinality = cardinality + + def __repr__(self): + return '<%s %s %i>' % (self.__class__.__name__, str(self._variables[0]), self.cardinality) + + def estimateCost(self, domains): + return self.cost + + def narrow(self, domains): + """narrowing algorithm for the constraint""" + prop = domains[self.variable].property + props = Linkeddict(domains[prop].getValues()) + dom = domains[self.variable].getValues() + if not dom: + return 0 + cls = dom[0] + card = get_cardinality(props, cls) + if card > self.cardinality: + raise ConsistencyFailure("Maxcardinality of %i exceeded by the value %i" %(self.cardinality,len(props[cls]))) + else: + return 1 + +class MinCardinality(MaxCardinality): + + def narrow(self, domains): + """narrowing algorithm for the constraint""" + prop = domains[self.variable].property + props = Linkeddict(domains[prop].getValues()) + cls = domains[self.variable].getValues()[0] + card = get_cardinality(props, cls) + if card < self.cardinality: + raise ConsistencyFailure("MinCardinality of %i not achieved by the value %i" %(self.cardinality,len(props[cls]))) + else: + return 1 + +class Cardinality(MaxCardinality): + + def narrow(self, domains): + """narrowing algorithm for the constraint""" + prop = domains[self.variable].property + props = Linkeddict(domains[prop].getValues()) + cls = domains[self.variable].getValues()[0] + card = get_cardinality(props, cls) + if card != self.cardinality: + raise ConsistencyFailure("Cardinality of %i exceeded by the value %r for %r" % + (self.cardinality, props[cls], prop)) + else: + return 1 + +class SubClassConstraint(AbstractConstraint): + + cost=1 + + def __init__(self, variable, cls_or_restriction): + AbstractConstraint.__init__(self, [variable, cls_or_restriction]) + self.object = cls_or_restriction + self.variable = variable + + def estimateCost(self, domains): + return self.cost + + def __repr__(self): + return '<%s %s %s>' % (self.__class__.__name__, str(self._variables[0]), self.object) + + def narrow(self, domains): + subdom = domains[self.variable] + superdom = domains[self.object] + vals = [] + vals += superdom.getValues() + vals += subdom.getValues() +[self.variable] + superdom.setValues(vals) + + return 0 + +class DisjointClassConstraint(SubClassConstraint): + + def narrow(self, domains): + subdom = domains[self.variable] + superdom = domains[self.object] + vals1 = superdom.getValues() + vals2 = subdom.getValues() + for i in vals1: + if i in vals2: + raise ConsistencyFailure() + +class ComplementClassConstraint(SubClassConstraint): + + def narrow(self, domains): + subdom = domains[self.variable] + superdom = domains[self.object] + +class RangeConstraint(SubClassConstraint): + + cost = 30 + + def narrow(self, domains): + propdom = domains[self.variable] + rangedom = domains[self.object] + newrange = rangedom.getValues() + res = [] + oldrange = propdom.range + if oldrange: + for v in oldrange: + if v in newrange: + res.append(v) + else: + res = newrange + propdom.range = res + propdom.setValues([(None,i) for i in res]) + #prop = Linkeddict(propdom.getValues()) + #for pval in sum(prop.values(),[]): + # if pval not in range: + # raise ConsistencyFailure("Value %r not in range %r for Var %s"%(pval,range, self.variable)) + +class DomainConstraint(SubClassConstraint): + + cost = 200 + + def narrow(self, domains): + propdom = domains[self.variable] + domaindom = domains[self.object] + newdomain = domaindom.getValues() +[self.object] + domain = [] + olddomain = propdom.domain + if olddomain: + for v in olddomain: + if v in newdomain: + domain.append(v) + else: + domain = newdomain + propdom.domain = domain + prop = Linkeddict(propdom.getValues()) + for pval in prop.keys(): + if pval not in domain: + raise ConsistencyFailure("Value %r not in range %r"%(pval, domain)) + +class SubPropertyConstraint(SubClassConstraint): + + def narrow(self, domains): + subdom = domains[self.variable] + superdom = domains[self.object] + vals = superdom.getValues() + for val in subdom.getValues(): + if not val in vals: + vals.append(val) + superdom.setValues(vals) + +class EquivalentPropertyConstraint(SubClassConstraint): + + cost = 100 + + def narrow(self, domains): + subdom = domains[self.variable] + superdom = domains[self.object] + vals = superdom.getValues() + for val in subdom.getValues(): + if not val in vals: + raise ConsistencyFailure("The Property %s is not equivalent to Property %s" % + (self.variable, self.object)) + +class TypeConstraint(SubClassConstraint): + cost = 1 + def narrow(self, domains): + subdom = domains[self.variable] + superdom = domains[self.object] + vals = [] + vals += superdom.getValues() + vals.append(self.variable) + superdom.setValues(vals) + return 1 + +class FunctionalCardinality(OwlConstraint): + """Contraint: all values must be distinct""" + + def narrow(self, domains): + """narrowing algorithm for the constraint""" + domain = domains[self.variable].getValues() + domain_dict = Linkeddict(domain) + for cls, val in domain_dict.items(): + if len(val) != 1: + raise ConsistencyFailure("FunctionalCardinality error") + else: + return 0 + +class InverseFunctionalCardinality(OwlConstraint): + """Contraint: all values must be distinct""" + + def narrow(self, domains): + """narrowing algorithm for the constraint""" + domain = domains[self.variable].getValues() + vals = {} + for cls, val in domain: + if vals.has_key(val): + raise ConsistencyFailure("InverseFunctionalCardinality error") + else: + vals[val] = 1 + else: + return 0 + +class Linkeddict(dict): + def __init__(self, values=()): + for k,v in values: + dict.setdefault(self,k,[]) + if type(v) == list: + dict.__setitem__(self, k, v) + else: + if not v in dict.__getitem__(self,k): + dict.__getitem__(self,k).append(v) + +class TransitiveConstraint(OwlConstraint): + """Contraint: all values must be distinct""" + + def narrow(self, domains): + """narrowing algorithm for the constraint""" + domain = domains[self.variable].getValues() + domain_dict = Linkeddict(domain) + for cls, val in domain: + if val in domain_dict: + for v in domain_dict[val]: + domain.append((cls,v)) + domains[self.variable].setValues(domain) + +class SymmetricConstraint(OwlConstraint): + """Contraint: all values must be distinct""" + + def narrow(self, domains): + """narrowing algorithm for the constraint""" + domain = domains[self.variable].getValues() + for cls, val in domain: + if not (val, cls) in domain: + domain.append((val,cls)) + domains[self.variable].setValues(domain) + +class InverseofConstraint(SubClassConstraint): + """Contraint: all values must be distinct""" + cost = 200 + + def narrow(self, domains): + """narrowing algorithm for the constraint""" + obj_domain = domains[self.object].getValues() + sub_domain = domains[self.variable].getValues() + res = [] + for cls, val in obj_domain: + if not (val,cls) in sub_domain: + raise ConsistencyFailure("Inverseof failed for (%r, %r) in %r" % + (val, cls, sub_domain) ) + for cls, val in sub_domain: + if not (val,cls) in obj_domain: + raise ConsistencyFailure("Inverseof failed for (%r, %r) in %r" % + (val, cls, obj_domain)) + +class DifferentfromConstraint(SubClassConstraint): + + def narrow(self, domains): + if self.variable == self.object: + raise ConsistencyFailure("%s can't be differentFrom itself" % self.variable) + else: + return 0 + +class SameasConstraint(SubClassConstraint): + + def narrow(self, domains): + if self.variable == self.object: + return 1 + else: + for dom in domains.values(): + vals = dom.getValues() + if hasattr(dom, '_dict'): + val = Linkeddict(vals) + if self.variable in val.keys() and not self.object in val.keys(): + vals +=[(self.object,v) for v in val[self.variable]] + dom.setValues(vals) + elif not self.variable in val.keys() and self.object in val.keys(): + vals +=[(self.variable,v) for v in val[self.object]] + dom.setValues(vals) + elif self.variable in val.keys() and self.object in val.keys(): + if not val[self.object] == val[self.variable]: + raise ConsistencyFailure("Sameas failure: The two individuals (%s, %s) \ + has different values for property %r"%(self.variable, self.object, dom)) + else: + if self.variable in vals and not self.object in vals: + vals.append(self.object) + elif not self.variable in vals and self.object in vals: + vals.append(self.variable) + else: + continue + dom.setValues(vals) + return 0 + +class ListConstraint(OwlConstraint): + """Contraint: all values must be distinct""" + + cost = 10 + + def narrow(self, domains): + """narrowing algorithm for the constraint""" + + vals =[] + vals += domains[self.variable].getValues() + if vals == []: + return 0 + while True: + if vals[-1] in domains.keys() and isinstance(domains[vals[-1]], List): + vals = vals[:-1] + domains[vals[-1]].getValues() + if domains[vals[-1]].remove : + domains.pop(vals[-1]) + else: + break + domains[self.variable].setValues(vals) + return 1 + +class RestrictionConstraint(OwlConstraint): + + cost = 70 + + def narrow(self, domains): + prop = domains[self.variable].property + vals = domains[self.variable].getValues() + if vals: + cls = vals[0] + props = domains[prop].getValues() + props.append((cls, None)) + domains[prop].setValues(props) + return 1 + else: + return 0 + +class OneofPropertyConstraint(AbstractConstraint): + + def __init__(self, variable, list_of_vals): + AbstractConstraint.__init__(self, [variable ]) + self.variable = variable + self.List = list_of_vals + cost = 100 + + def estimateCost(self, domains): + return self.cost + + def narrow(self, domains): + val = domains[self.List].getValues() + if isinstance(domains[self.variable],Restriction): + # This should actually never happen ?? + property = domains[self.variable].property + cls = domains[self.variable].getValues()[0] + prop = Linkeddict(domains[property].getValues()) + for v in prop[cls]: + if not v in val: + raise ConsistencyFailure( + "The value of the property %s in the class %s is not oneof %r" + %(property, cls, val)) + else: + domains[self.variable].setValues(val) + return 1 + +class UnionofConstraint(OneofPropertyConstraint): + + cost = 200 + + def narrow(self, domains): + val = domains[self.List].getValues() + union = [] + for v in val: + for u in domains[v].getValues(): + if not u in union: + union.append(u) + cls = domains[self.variable].setValues(union) + +class IntersectionofConstraint(OneofPropertyConstraint): + + cost = 200 + + def narrow(self, domains): + val = domains[self.List].getValues() + intersection = domains[val[0]].getValues() + for v in val[1:]: + vals= domains[v].getValues() + remove = [] + for u in intersection: + if not u in vals: + remove.append(u) + for u in remove: + intersection.remove(u) + cls = domains[self.variable].setValues(intersection) + term = {} + for l in [domains[x] for x in val]: + if hasattr(l,'TBox'): + TBox = l.TBox + prop = l.property + for item in TBox.values(): + term.setdefault(prop,[]) + term[prop].append(item) + for prop in term: + axioms = term[prop] + ranges = [ax[0] for ax in axioms] + res = [] + while axioms: + r, comp = axioms.pop(0) + if res: + res = [x for x in res if eval('x %s r' % comp)] + else: + res = [x for x in r if eval('x %s r' % comp)] + if not res: + axioms.append((r,comp)) + if not res: + raise ConsistencyFailure("Inconsistent use of intersectionOf") + +class SomeValueConstraint(OneofPropertyConstraint): + + cost = 100 + + def narrow(self, domains): + val = domains[self.List].getValues() + property = domains[self.variable].property + cls = domains[self.variable].getValues()[0] + prop = Linkeddict(domains[property].getValues()) + for v in prop[cls]: + if v in val: + break + else: + raise ConsistencyFailure( + "The value of the property %s in the class %s has no values from %r" + %(property, cls, val)) + +class AllValueConstraint(OneofPropertyConstraint): + + cost = 100 + + def narrow(self, domains): + val = domains[self.List].getValues() + property = domains[self.variable].property + cls = domains[self.variable].getValues()[0] + prop = Linkeddict(domains[property].getValues()) + for v in prop[cls]: + if not v in val: + raise ConsistencyFailure( + "The value of the property %s in the class %s has a value not from %r" + %(property, cls, val)) + +class HasvalueConstraint(AbstractConstraint): + + def __init__(self, variable, List): + AbstractConstraint.__init__(self, [variable]) + self.variable = variable + self.List = List + + cost = 100 + + def estimateCost(self, domains): + return self.cost + + def narrow(self, domains): + val = self.List + property = domains[self.variable].property + cls = domains[self.variable].getValues()[0] + prop = Linkeddict(domains[property].getValues()) + for v in prop[cls]: + if v == val: + break + else: + raise ConsistencyFailure( + "The value of the property %s in the class %s has a value not from %r" + %(property, cls, val)) + Modified: pypy/dist/pypy/lib/pyontology/pyontology.py ============================================================================== --- pypy/dist/pypy/lib/pyontology/pyontology.py (original) +++ pypy/dist/pypy/lib/pyontology/pyontology.py Fri May 5 10:05:19 2006 @@ -2,6 +2,7 @@ from logilab.constraint import Repository, Solver from logilab.constraint.fd import FiniteDomain as fd from logilab.constraint.propagation import AbstractDomain, AbstractConstraint, ConsistencyFailure +from constraint_classes import * import sys, py import time @@ -13,7 +14,7 @@ } uris = {} -for k,v in namespaces.items(): +for k,v in namespaces.items(): uris[v] = k Class = URIRef(u'http://www.w3.org/2002/07/owl#Class') @@ -36,16 +37,15 @@ else: format = "n3" return format - class ClassDomain(AbstractDomain): - + # Class domain is intended as a (abstract/virtual) domain for implementing # Class axioms. Working on class descriptions the class domain should allow # creation of classes through axioms. # The instances of a class can be represented as a FiniteDomain in values (not always see Disjointwith) # Properties of a class is in the dictionary "properties" # The bases of a class is in the list "bases" - + def __init__(self, name='', values=[], bases = []): AbstractDomain.__init__(self) self.bases = bases+[self] @@ -54,46 +54,46 @@ self.name = name self.properties = {} # The TBox is a dictionary containing terminology constraints - # on predicates for this class. Keys are predicates, constraint + # on predicates for this class. Keys are predicates, constraint # tupples ie. (p,'Carddinality') and values are list, comparison # tupples self.TBox = {} - # The ABox contains the constraints the individuals of the class - # shall comply to + # The ABox contains the constraints the individuals of the class + # shall comply to self.ABox = {} - + def __repr__(self): return "<%s %s %r>" % (self.__class__, str(self.name),self.getValues()) - + def __getitem__(self, index): return None - + def __iter__(self): - return iter(self.bases) - + return iter(self.bases) + def size(self): return len(self.bases) - + __len__ = size - + def copy(self): return self - + def removeValues(self, values): for val in values: self.values.pop(self.values.index(val)) - + def getBases(self): return self.bases - + def getValues(self): return self.values.keys() - + def setValues(self, values): self.values = dict.fromkeys(values) class List(ClassDomain): - + def __init__(self, name='', values=[], bases = []): ClassDomain.__init__(self, name, values, bases) self.constraint = ListConstraint(name) @@ -101,14 +101,14 @@ class Property(ClassDomain): # Property contains the relationship between a class instance and a value # - a pair. To accomodate global assertions like 'range' and 'domain' attributes - # for range and domain must be filled in by rdfs:range and rdfs:domain - + # for range and domain must be filled in by rdfs:range and rdfs:domain + def __init__(self, name='', values=[], bases = []): ClassDomain.__init__(self, name, values, bases) self._dict = Linkeddict() self.range = [] self.domain = [] - + def getValues(self): items = self._dict.items() res = [] @@ -120,20 +120,20 @@ def addValue(self, key, val): self._dict.setdefault(key, []) self._dict[key].append(val) - + def setValues(self, values): self._dict = Linkeddict(values) - + def removeValues(self, values): for k,v in values: vals = self._dict[k] if vals == [None]: self._dict.pop(k) else: - self._dict[k] = [ x for x in vals if x != v] - -class ObjectProperty(Property): + self._dict[k] = [ x for x in vals if x != v] +class ObjectProperty(Property): + pass class DatatypeProperty(Property): @@ -151,7 +151,7 @@ pass class Nothing(ClassDomain): - + pass @@ -160,7 +160,7 @@ def __init__(self, name='', values=[], bases = []): Property.__init__(self, name, values, bases) self.constraint = FunctionalCardinality(name) - + class InverseFunctionalProperty(Property): def __init__(self, name='', values=[], bases = []): @@ -183,9 +183,9 @@ """ A owl:restriction is an anonymous class that links a class to a restriction on a property The restriction is only applied to the property in the conntext of the specific task. In order to construct a constraint to check the restriction three things are thus needed : - 1. The property to which the restriction applies - this comes from the onProperty tripple. + 1. The property to which the restriction applies - this comes from the onProperty tripple. the property is saved in the Restriction class' property attribute - 2. The restriction itself. This comes from one of the property restrictions triples (oneOf, + 2. The restriction itself. This comes from one of the property restrictions triples (oneOf, maxCardinality ....). It adds a constraint class 3. The class in which context the restriction should be applied. This comes from subClassOf, type... The class is saved in the restrictions cls attribute @@ -194,7 +194,7 @@ ClassDomain.__init__(self, name, values, bases) self.constraint = RestrictionConstraint(name) self.property = None - + builtin_voc = { getUriref('owl', 'Thing') : Thing, getUriref('owl', 'Class') : ClassDomain, @@ -215,9 +215,9 @@ getUriref('owl', 'TransitiveProperty') : TransitiveProperty, getUriref('rdf', 'List') : List } - -class Ontology: +class Ontology: + def __init__(self, store = 'default'): self.graph = Graph(store) if store != 'default': @@ -226,47 +226,54 @@ self.constraints = [] self.seen = {} self.var2ns ={} - + def add(self, triple): self.graph.add(triple) - + def add_file(self, f, format=None): if not format: format = check_format(f) self.graph.load(f, format=format) - + def attach_fd(self): for (s, p, o) in (self.graph.triples((None,)*3)): - if p.find('#') != -1: - ns, func = p.split('#') - else: - ns ='' - func = p - if ns in namespaces.values(): - #predicate is one of builtin OWL or rdf predicates - pred = getattr(self, func) - res = pred(s, o) - if not res : - continue - if type(res) != list : - res = [res] - avar = self.make_var(ClassDomain, s) - else: - avar = self.make_var(Property, p) - # Set the values of the property p to o - sub = self.make_var(ClassDomain, s) - obj = self.make_var(Thing, o) - propdom = self.variables[avar] - res = propdom.addValue(sub, obj) + if (s, p, o) in self.seen: + continue + self.seen[(s, p, o)] = True + self.consider_triple((s, p, o)) + + def consider_triple(self,(s, p, o)): + if p.find('#') != -1: + ns, func = p.split('#') + else: + ns ='' + func = p + if ns in namespaces.values(): + #predicate is one of builtin OWL or rdf predicates + pred = getattr(self, func) + res = pred(s, o) + if not res : + return + if type(res) != list : + res = [res] + avar = self.make_var(ClassDomain, s) + else: + avar = self.make_var(Property, p) + # Set the values of the property p to o + sub = self.make_var(ClassDomain, s) + obj = self.make_var(Thing, o) + propdom = self.variables[avar] + res = propdom.addValue(sub, obj) + def solve(self,verbose=0): rep = Repository(self.variables.keys(), self.variables, self.constraints) return Solver().solve(rep, verbose) - + def consistency(self, verbose=0): self.rep = Repository(self.variables.keys(), self.variables, self.constraints) self.rep.consistency(verbose) - + def flatten_rdf_list(self, rdf_list): res = [] if not type(rdf_list) == list: @@ -280,7 +287,7 @@ res.append(list(self.graph.objects(lis, rdf_first))[0]) lis = list(self.graph.objects(lis, rdf_rest))[0] else: - # For testing + # For testing avar = self.make_var(List, BNode('anon_%r'%rdf_list)) if type(rdf_list[0]) == list: res = [tuple(x) for x in rdf_list] @@ -288,7 +295,15 @@ res = rdf_list self.variables[avar].setValues(res) return avar - + + def resolve_item(self, item): + item_as_subject = self.graph.triples((item, None, None)) + for triple in item_as_subject: + if triple in self.seen: + continue + self.seen[triple] = True + self.consider_triple(triple) + def make_var(self, cls=fd, a=''): if type(a) == URIRef: if a.find('#') != -1: @@ -297,7 +312,7 @@ ns,name = a,'' if ns not in uris.keys(): uris[ns] = ns.split('/')[-1] - a = uris[ns] + '_' + name + a = uris[ns] + '_' + name var = str(a.replace('-','_')) else: var = a @@ -309,13 +324,13 @@ vals = self.variables[var].getValues() self.variables[var] = cls(var) self.variables[var].setValues(vals) - return var + return var #---------------- Implementation ---------------- - + def comment(self, s, var): pass - + def type(self, s, var): if not var in builtin_voc : # var is not one of the builtin classes @@ -330,16 +345,16 @@ return else: svar = self.make_var(None, s) - if not (self.variables.has_key(svar) and + if not (self.variables.has_key(svar) and isinstance(self.variables[svar], cls)): svar = self.make_var(cls, s) cls = self.variables[svar] if hasattr(cls, 'constraint'): self.constraints.append(cls.constraint) - + def first(self, s, var): pass - + def rest(self, s, var): pass @@ -347,49 +362,49 @@ svar =self.make_var(Restriction, s) avar =self.make_var(Property, var) self.variables[svar].property = avar - -#---Class Axioms---#000000#FFFFFF----------------------------------------------- +#---Class Axioms---#000000#FFFFFF----------------------------------------------- + def subClassOf(self, s, var): - # s is a subclass of var means that the + # s is a subclass of var means that the # class extension of s is a subset of the - # class extension of var, ie if a indiviual is in + # class extension of var, ie if a indiviual is in # the extension of s it must be in the extension of # var avar = self.make_var(None, var) svar = self.make_var(ClassDomain, s) cons = SubClassConstraint( svar, avar) self.constraints.append(cons) - + def equivalentClass(self, s, var): self.subClassOf(s, var) self.subClassOf(var, s) - + def disjointWith(self, s, var): avar = self.make_var(None, var) svar = self.make_var(None, s) - constrain = DisjointClassConstraint(svar, avar) + constrain = DisjointClassConstraint(svar, avar) self.constraints.append(constrain) - + def complementOf(self, s, var): # add constraint of not var # TODO: implementthis for OWL DL ## avar = self.make_var(ClassDomain, var) ## svar = self.make_var(ClassDomain, s) pass - + def oneOf(self, s, var): var = self.flatten_rdf_list(var) #avar = self.make_var(List, var) svar = self.make_var(ClassDomain, s) res = self.variables[var].getValues() self.variables[svar].setValues(res) - + def unionOf(self,s, var): var = self.flatten_rdf_list(var) vals = self.variables[var].getValues() - + res = [] for val in vals: res.extend([x for x in val]) @@ -397,7 +412,7 @@ vals = self.variables[svar].getValues() res.extend(vals) self.variables[svar].setValues(res) - + def intersectionOf(self, s, var): var = self.flatten_rdf_list(var) vals = self.variables[var].getValues() @@ -412,33 +427,33 @@ self.variables[svar].setValues(res) #---Property Axioms---#000000#FFFFFF-------------------------------------------- - + def range(self, s, var): avar = self.make_var(ClassDomain, var) svar = self.make_var(Property, s) cons = RangeConstraint(svar, avar) self.constraints.append(cons) - + def domain(self, s, var): # The classes that has this property (s) must belong to the class extension of var avar = self.make_var(ClassDomain, var) svar = self.make_var(Property, s) cons = DomainConstraint(svar, avar) self.constraints.append(cons) - + def subPropertyOf(self, s, var): # s is a subproperty of var avar = self.make_var(Property, var) svar = self.make_var(Property, s) cons = SubPropertyConstraint( svar, avar) self.constraints.append(cons) - + def equivalentProperty(self, s, var): avar = self.make_var(Property, var) svar = self.make_var(Property, s) cons = EquivalentPropertyConstraint( svar, avar) self.constraints.append(cons) - + def inverseOf(self, s, var): avar = self.make_var(Property, var) svar = self.make_var(Property, s) @@ -446,39 +461,39 @@ self.constraints.append(con) #---Property restrictions------------------------------------------------------ - + def maxCardinality(self, s, var): """ Len of finite domain of the property shall be less than or equal to var""" svar =self.make_var(Restriction, s) constrain = MaxCardinality(svar, int(var)) - self.constraints.append(constrain) + self.constraints.append(constrain) # Make a new variable that can hold the domain of possible cardinality # values self.variables[svar].TBox['Cardinality'] = (range( int(var)+1), 'in') # var_name = '%s_Cardinality' % svar # self.variables[var_name] = fd(range(int(var)+1)) - + def minCardinality(self, s, var): """ Len of finite domain of the property shall be greater than or equal to var""" svar =self.make_var(Restriction, s) constrain = MinCardinality(svar, int(var)) - self.constraints.append(constrain) + self.constraints.append(constrain) self.variables[svar].TBox['Cardinality'] = ( range(int(var)), 'not in') # var_name = '%s_Cardinality' % svar # self.variables[var_name] = fd(range(int(var))) # constraint = Expression(var_name,' not in') # self.constraints.append(constraint) - + def cardinality(self, s, var): """ Len of finite domain of the property shall be equal to var""" svar =self.make_var(Restriction, s) # Check if var is an int, else find the int buried in the structure constrain = Cardinality(svar, int(var)) - self.constraints.append(constrain) + self.constraints.append(constrain) self.variables[svar].TBox['Cardinality'] = ( [int(var)], 'in') # var_name = '%s_Cardinality' % svar -# self.variables['var_name'] = fd(int(var)) - +# self.variables['var_name'] = fd(int(var)) + def differentFrom(self, s, var): s_var = self.make_var(Thing, s) var_var = self.make_var(Thing, var) @@ -491,532 +506,38 @@ var_var = self.flatten_rdf_list(var) #var_var = self.make_var(List, var) for v in var_var: - indx = var_var.index(v) + indx = var_var.index(v) for other in var_var[indx+1:]: self.differentFrom(v, other) constrain = AllDifferentConstraint(s_var, var_var) self.constraints.append(constrain) - + def sameAs(self, s, var): s_var = self.make_var(None, s) var_var = self.make_var(None, var) constrain = SameasConstraint(s_var, var_var) self.constraints.append(constrain) - + def hasValue(self, s, var): svar = self.make_var(Restriction, s) avar = self.make_var(None, var) constrain = HasvalueConstraint(svar, avar) self.constraints.append(constrain) - + def allValuesFrom(self, s, var): svar = self.make_var(Restriction, s) avar = self.make_var(None, var) constrain = AllValueConstraint(svar, avar) self.constraints.append(constrain) - + def someValuesFrom(self, s, var): svar = self.make_var(Restriction, s) avar = self.make_var(None, var) constrain = SomeValueConstraint(svar, avar) self.constraints.append(constrain) - + def imports(self, s, var): - # PP TODO: implement this + # PP TODO: implement this pass # ----------------- Helper classes ---------------- - -class OwlConstraint(AbstractConstraint): - - cost = 1 - - def __init__(self, variable): - AbstractConstraint.__init__(self, [variable]) - self.variable = variable - - def __repr__(self): - return '<%s %s>' % (self.__class__.__name__, str(self._variables[0])) - - def estimateCost(self, domains): - return self.cost - -def get_cardinality(props, cls): - if props.get(cls): - card = len(props[cls]) - elif props.get(None): - card = len(props[None]) - else: - card = 0 - return card - -class MaxCardinality(AbstractConstraint): - """Contraint: all values must be distinct""" - - def __init__(self, variable, cardinality): - AbstractConstraint.__init__(self, [variable]) - self.cost = 80 - self.variable = variable - self.cardinality = cardinality - - def __repr__(self): - return '<%s %s %i>' % (self.__class__.__name__, str(self._variables[0]), self.cardinality) - - def estimateCost(self, domains): - return self.cost - - def narrow(self, domains): - """narrowing algorithm for the constraint""" - prop = domains[self.variable].property - props = Linkeddict(domains[prop].getValues()) - dom = domains[self.variable].getValues() - if not dom: - return 0 - cls = dom[0] - card = get_cardinality(props, cls) - if card > self.cardinality: - raise ConsistencyFailure("Maxcardinality of %i exceeded by the value %i" %(self.cardinality,len(props[cls]))) - else: - return 1 - -class MinCardinality(MaxCardinality): - - def narrow(self, domains): - """narrowing algorithm for the constraint""" - prop = domains[self.variable].property - props = Linkeddict(domains[prop].getValues()) - cls = domains[self.variable].getValues()[0] - card = get_cardinality(props, cls) - if card < self.cardinality: - raise ConsistencyFailure("MinCardinality of %i not achieved by the value %i" %(self.cardinality,len(props[cls]))) - else: - return 1 - -class Cardinality(MaxCardinality): - - def narrow(self, domains): - """narrowing algorithm for the constraint""" - prop = domains[self.variable].property - props = Linkeddict(domains[prop].getValues()) - cls = domains[self.variable].getValues()[0] - card = get_cardinality(props, cls) - if card != self.cardinality: - raise ConsistencyFailure("Cardinality of %i exceeded by the value %r for %r" % - (self.cardinality, props[cls], prop)) - else: - return 1 - -class SubClassConstraint(AbstractConstraint): - - cost=1 - - def __init__(self, variable, cls_or_restriction): - AbstractConstraint.__init__(self, [variable, cls_or_restriction]) - self.object = cls_or_restriction - self.variable = variable - - def estimateCost(self, domains): - return self.cost - - def __repr__(self): - return '<%s %s %s>' % (self.__class__.__name__, str(self._variables[0]), self.object) - - def narrow(self, domains): - subdom = domains[self.variable] - superdom = domains[self.object] - vals = [] - vals += superdom.getValues() - vals += subdom.getValues() +[self.variable] - superdom.setValues(vals) - - return 0 - -class DisjointClassConstraint(SubClassConstraint): - - def narrow(self, domains): - subdom = domains[self.variable] - superdom = domains[self.object] - vals1 = superdom.getValues() - vals2 = subdom.getValues() - for i in vals1: - if i in vals2: - raise ConsistencyFailure() - -class ComplementClassConstraint(SubClassConstraint): - - def narrow(self, domains): - subdom = domains[self.variable] - superdom = domains[self.object] - -class RangeConstraint(SubClassConstraint): - - cost = 30 - - def narrow(self, domains): - propdom = domains[self.variable] - rangedom = domains[self.object] - newrange = rangedom.getValues() - res = [] - oldrange = propdom.range - if oldrange: - for v in oldrange: - if v in newrange: - res.append(v) - else: - res = newrange - propdom.range = res - propdom.setValues([(None,i) for i in res]) - #prop = Linkeddict(propdom.getValues()) - #for pval in sum(prop.values(),[]): - # if pval not in range: - # raise ConsistencyFailure("Value %r not in range %r for Var %s"%(pval,range, self.variable)) - -class DomainConstraint(SubClassConstraint): - - cost = 200 - - def narrow(self, domains): - propdom = domains[self.variable] - domaindom = domains[self.object] - newdomain = domaindom.getValues() +[self.object] - domain = [] - olddomain = propdom.domain - if olddomain: - for v in olddomain: - if v in newdomain: - domain.append(v) - else: - domain = newdomain - propdom.domain = domain - prop = Linkeddict(propdom.getValues()) - for pval in prop.keys(): - if pval not in domain: - raise ConsistencyFailure("Value %r not in range %r"%(pval, domain)) - -class SubPropertyConstraint(SubClassConstraint): - - def narrow(self, domains): - subdom = domains[self.variable] - superdom = domains[self.object] - vals = superdom.getValues() - for val in subdom.getValues(): - if not val in vals: - vals.append(val) - superdom.setValues(vals) - -class EquivalentPropertyConstraint(SubClassConstraint): - - cost = 100 - - def narrow(self, domains): - subdom = domains[self.variable] - superdom = domains[self.object] - vals = superdom.getValues() - for val in subdom.getValues(): - if not val in vals: - raise ConsistencyFailure("The Property %s is not equivalent to Property %s" % - (self.variable, self.object)) - -class TypeConstraint(SubClassConstraint): - cost = 1 - def narrow(self, domains): - subdom = domains[self.variable] - superdom = domains[self.object] - vals = [] - vals += superdom.getValues() - vals.append(self.variable) - superdom.setValues(vals) - return 1 - -class FunctionalCardinality(OwlConstraint): - """Contraint: all values must be distinct""" - - def narrow(self, domains): - """narrowing algorithm for the constraint""" - domain = domains[self.variable].getValues() - domain_dict = Linkeddict(domain) - for cls, val in domain_dict.items(): - if len(val) != 1: - raise ConsistencyFailure("FunctionalCardinality error") - else: - return 0 - -class InverseFunctionalCardinality(OwlConstraint): - """Contraint: all values must be distinct""" - - def narrow(self, domains): - """narrowing algorithm for the constraint""" - domain = domains[self.variable].getValues() - vals = {} - for cls, val in domain: - if vals.has_key(val): - raise ConsistencyFailure("InverseFunctionalCardinality error") - else: - vals[val] = 1 - else: - return 0 - -class Linkeddict(dict): - def __init__(self, values=()): - for k,v in values: - dict.setdefault(self,k,[]) - if type(v) == list: - dict.__setitem__(self, k, v) - else: - if not v in dict.__getitem__(self,k): - dict.__getitem__(self,k).append(v) - -class TransitiveConstraint(OwlConstraint): - """Contraint: all values must be distinct""" - - def narrow(self, domains): - """narrowing algorithm for the constraint""" - domain = domains[self.variable].getValues() - domain_dict = Linkeddict(domain) - for cls, val in domain: - if val in domain_dict: - for v in domain_dict[val]: - domain.append((cls,v)) - domains[self.variable].setValues(domain) - -class SymmetricConstraint(OwlConstraint): - """Contraint: all values must be distinct""" - - def narrow(self, domains): - """narrowing algorithm for the constraint""" - domain = domains[self.variable].getValues() - for cls, val in domain: - if not (val, cls) in domain: - domain.append((val,cls)) - domains[self.variable].setValues(domain) - -class InverseofConstraint(SubClassConstraint): - """Contraint: all values must be distinct""" - cost = 200 - - def narrow(self, domains): - """narrowing algorithm for the constraint""" - obj_domain = domains[self.object].getValues() - sub_domain = domains[self.variable].getValues() - res = [] - for cls, val in obj_domain: - if not (val,cls) in sub_domain: - raise ConsistencyFailure("Inverseof failed for (%r, %r) in %r" % - (val, cls, sub_domain) ) - for cls, val in sub_domain: - if not (val,cls) in obj_domain: - raise ConsistencyFailure("Inverseof failed for (%r, %r) in %r" % - (val, cls, obj_domain)) - -class DifferentfromConstraint(SubClassConstraint): - - def narrow(self, domains): - if self.variable == self.object: - raise ConsistencyFailure("%s can't be differentFrom itself" % self.variable) - else: - return 0 - -class SameasConstraint(SubClassConstraint): - - def narrow(self, domains): - if self.variable == self.object: - return 1 - else: - for dom in domains.values(): - vals = dom.getValues() - if isinstance(dom, Property): - val = Linkeddict(vals) - if self.variable in val.keys() and not self.object in val.keys(): - vals +=[(self.object,v) for v in val[self.variable]] - dom.setValues(vals) - elif not self.variable in val.keys() and self.object in val.keys(): - vals +=[(self.variable,v) for v in val[self.object]] - dom.setValues(vals) - elif self.variable in val.keys() and self.object in val.keys(): - if not val[self.object] == val[self.variable]: - raise ConsistencyFailure("Sameas failure: The two individuals (%s, %s) \ - has different values for property %r"%(self.variable, self.object, dom)) - else: - if self.variable in vals and not self.object in vals: - vals.append(self.object) - elif not self.variable in vals and self.object in vals: - vals.append(self.variable) - else: - continue - dom.setValues(vals) - return 0 - -class ListConstraint(OwlConstraint): - """Contraint: all values must be distinct""" - - cost = 10 - - def narrow(self, domains): - """narrowing algorithm for the constraint""" - - vals =[] - vals += domains[self.variable].getValues() - if vals == []: - return 0 - while True: - if vals[-1] in domains.keys() and isinstance(domains[vals[-1]], List): - vals = vals[:-1] + domains[vals[-1]].getValues() - if domains[vals[-1]].remove : - domains.pop(vals[-1]) - else: - break - domains[self.variable].setValues(vals) - return 1 - -class RestrictionConstraint(OwlConstraint): - - cost = 70 - - def narrow(self, domains): - prop = domains[self.variable].property - vals = domains[self.variable].getValues() - if vals: - cls = vals[0] - props = domains[prop].getValues() - props.append((cls, None)) - domains[prop].setValues(props) - return 1 - else: - return 0 - -class OneofPropertyConstraint(AbstractConstraint): - - def __init__(self, variable, list_of_vals): - AbstractConstraint.__init__(self, [variable ]) - self.variable = variable - self.List = list_of_vals - cost = 100 - - def estimateCost(self, domains): - return self.cost - - def narrow(self, domains): - val = domains[self.List].getValues() - if isinstance(domains[self.variable],Restriction): - # This should actually never happen ?? - property = domains[self.variable].property - cls = domains[self.variable].getValues()[0] - prop = Linkeddict(domains[property].getValues()) - for v in prop[cls]: - if not v in val: - raise ConsistencyFailure( - "The value of the property %s in the class %s is not oneof %r" - %(property, cls, val)) - else: - domains[self.variable].setValues(val) - return 1 - -class UnionofConstraint(OneofPropertyConstraint): - - cost = 200 - - def narrow(self, domains): - val = domains[self.List].getValues() - union = [] - for v in val: - for u in domains[v].getValues(): - if not u in union: - union.append(u) - cls = domains[self.variable].setValues(union) - -class IntersectionofConstraint(OneofPropertyConstraint): - - cost = 200 - - def narrow(self, domains): - val = domains[self.List].getValues() - intersection = domains[val[0]].getValues() - for v in val[1:]: - vals= domains[v].getValues() - remove = [] - for u in intersection: - if not u in vals: - remove.append(u) - for u in remove: - intersection.remove(u) - cls = domains[self.variable].setValues(intersection) - term = {} - for l in [domains[x] for x in val]: - if hasattr(l,'TBox'): - TBox = l.TBox - prop = l.property - for item in TBox.values(): - term.setdefault(prop,[]) - term[prop].append(item) - for prop in term: - axioms = term[prop] - ranges = [ax[0] for ax in axioms] - res = [] - while axioms: - r, comp = axioms.pop(0) - if res: - res = [x for x in res if eval('x %s r' % comp)] - else: - res = [x for x in r if eval('x %s r' % comp)] - if not res: - axioms.append((r,comp)) - if not res: - raise ConsistencyFailure("Inconsistent use of intersectionOf") - -class SomeValueConstraint(OneofPropertyConstraint): - - cost = 100 - - def narrow(self, domains): - val = domains[self.List].getValues() - property = domains[self.variable].property - cls = domains[self.variable].getValues()[0] - prop = Linkeddict(domains[property].getValues()) - for v in prop[cls]: - if v in val: - break - else: - raise ConsistencyFailure( - "The value of the property %s in the class %s has no values from %r" - %(property, cls, val)) - -class AllValueConstraint(OneofPropertyConstraint): - - cost = 100 - - def narrow(self, domains): - val = domains[self.List].getValues() - property = domains[self.variable].property - cls = domains[self.variable].getValues()[0] - prop = Linkeddict(domains[property].getValues()) - for v in prop[cls]: - if not v in val: - raise ConsistencyFailure( - "The value of the property %s in the class %s has a value not from %r" - %(property, cls, val)) - -class HasvalueConstraint(AbstractConstraint): - - def __init__(self, variable, List): - AbstractConstraint.__init__(self, [variable]) - self.variable = variable - self.List = List - - cost = 100 - - def estimateCost(self, domains): - return self.cost - - def narrow(self, domains): - val = self.List - property = domains[self.variable].property - cls = domains[self.variable].getValues()[0] - prop = Linkeddict(domains[property].getValues()) - for v in prop[cls]: - if v == val: - break - else: - raise ConsistencyFailure( - "The value of the property %s in the class %s has a value not from %r" - %(property, cls, val)) - Modified: pypy/dist/pypy/lib/pyontology/test/test_ontology.py ============================================================================== --- pypy/dist/pypy/lib/pyontology/test/test_ontology.py (original) +++ pypy/dist/pypy/lib/pyontology/test/test_ontology.py Fri May 5 10:05:19 2006 @@ -500,7 +500,7 @@ def test_cardinality_terminology(): - py.test.skip("In progress") + #py.test.skip("In progress") # Modeled after one of the standard tests (approved/maxCardinality) # 'cls' by subclassing two maxCardinality restrictions becomes the set of # individuals satisfying both restriction, ie having exactly 2 values of @@ -526,7 +526,7 @@ O.minCardinality(restr2, 3) constraints = len(O.constraints) py.test.raises(ConsistencyFailure, O.consistency, 3) - assert len(O.constraints) < constraints - py.test.raises(ConsistencyFailure, O.consistency, 3) + + assert 0 From bea at codespeak.net Fri May 5 10:53:33 2006 From: bea at codespeak.net (bea at codespeak.net) Date: Fri, 5 May 2006 10:53:33 +0200 (CEST) Subject: [pypy-svn] r26797 - pypy/extradoc/talk/agile2006 Message-ID: <20060505085333.5067310088@code0.codespeak.net> Author: bea Date: Fri May 5 10:53:21 2006 New Revision: 26797 Modified: pypy/extradoc/talk/agile2006/draftpaper_agile2006.txt Log: more finetuning based on feedback by Emily Bache... Modified: pypy/extradoc/talk/agile2006/draftpaper_agile2006.txt ============================================================================== --- pypy/extradoc/talk/agile2006/draftpaper_agile2006.txt (original) +++ pypy/extradoc/talk/agile2006/draftpaper_agile2006.txt Fri May 5 10:53:21 2006 @@ -691,11 +691,30 @@ This while working agile with open and transparent communication through sprints, documentation, tutorials, mentoring, sync-meetings. Resulting in a lively and growing the F/OSS community around the project. - -Drawing from these different skills within the community of developers in the -PyPy project one possible conclusion would be that a truly agile approach + +So, could it be said that for an agile software development process, especially one that is +distributed and community oriented, within a framework of EU-funding, that it is heavily +people dependent? Or to stress it even further, sprint-driven development as a methodology +does not exist and function without an agile group of people, Crack performers. The people +are the methodology in some sense and if you wish to draw upon the experience of the PyPy +team you need to look at the supporting practices around the people in order to find what can be +duplicated and tested in another project environment. This conclusion matches what Alistair +Cockburn writes in his paper "Characterizing People as Non-Linear, First-Order Components in +Software Development" [3]: + +"The fundamental characteristics of "people" have a first-order +effect on software development, not a lower-order effect." + +If we accept this conclusion then we can also, thanks to the people, start to get innovative +regarding practices. Designing the project process based on the specific needs of the unique +project environment you are facing. In the case of PyPy this means that we are exploring +the methodology as we go along, adjusting and finetuning the process as well as the software. + +So, when drawing from these different skills within the community of developers, the people, in +the PyPy project one possible conclusion would be that a truly agile approach dominating the work style of an Open Source project will increase the ability of the community to spread the strategy of agility to other domains. + By this we mean that what started as agile practices in the development process quickly became influencing factors when designing other project processes. Examples of this in PyPy is how the sprint-driven development acts as a focal point not just for the @@ -713,4 +732,15 @@ [2] Barry Boehm,Richard Turner, "Observations on Balancing Discipline and Agility", (drawn from the book "Balancing Agility and Discipline: A Guide to the Perplexed", -Addison Wesley, 2003) \ No newline at end of file +Addison Wesley, 2003) + +[3] Alistair Cockburn, "Characterizing People as Non-Linear, First-Order Components in +Software Development", Presented at the 4th International Multi-Conference on Systems, +Cybernetics and Informatics, Orlando, Florida, June, 2000, +http://alistair.cockburn.us/crystal/articles/cpanfocisd/characterizingpeopleasnonlinear.html + +The author would like to thank the following people who have in various ways helped with the +creation of this paper: Angela Martin, Emily Bache, Tres Seaver, Carl Friedrich Bolz. + +I would like to dedicate this paper to my dear friend and mentor of the Open Source Python and +PyPy community Holger Krekel. \ No newline at end of file From arigo at codespeak.net Fri May 5 10:55:43 2006 From: arigo at codespeak.net (arigo at codespeak.net) Date: Fri, 5 May 2006 10:55:43 +0200 (CEST) Subject: [pypy-svn] r26799 - in pypy/dist/pypy: annotation annotation/test rpython/lltypesystem rpython/ootypesystem rpython/test Message-ID: <20060505085543.7909810088@code0.codespeak.net> Author: arigo Date: Fri May 5 10:55:40 2006 New Revision: 26799 Modified: pypy/dist/pypy/annotation/classdef.py pypy/dist/pypy/annotation/test/test_annrpython.py pypy/dist/pypy/annotation/unaryop.py pypy/dist/pypy/rpython/lltypesystem/rclass.py pypy/dist/pypy/rpython/ootypesystem/rclass.py pypy/dist/pypy/rpython/test/test_rclass.py Log: (pedronis, arigo) Supports reading the __class__ attribute on instances. The result is a SomePBC of all possible classes, which is quite different from what type(x) returns, which is just SomeObject(knowntype=type). It means that .__class__ should be suitable for expressions like 'y = x.__class__()'. Modified: pypy/dist/pypy/annotation/classdef.py ============================================================================== --- pypy/dist/pypy/annotation/classdef.py (original) +++ pypy/dist/pypy/annotation/classdef.py Fri May 5 10:55:40 2006 @@ -67,6 +67,7 @@ # instances that have the attribute set will turn off readonly-ness. def __init__(self, name, bookkeeper): + assert name != '__class__' self.name = name self.bookkeeper = bookkeeper self.s_value = SomeImpossibleValue() @@ -131,10 +132,12 @@ self.shortname = self.name.split('.')[-1] self.subdefs = [] self.attr_sources = {} # {name: list-of-sources} + self.read_locations_of__class__ = {} if classdesc.basedesc: self.basedef = classdesc.basedesc.getuniqueclassdef() self.basedef.subdefs.append(self) + self.basedef.see_new_subclass(self) else: self.basedef = None @@ -370,6 +373,17 @@ else: return False + def see_new_subclass(self, classdef): + for position in self.read_locations_of__class__: + self.bookkeeper.annotator.reflowfromposition(position) + if self.basedef is not None: + self.basedef.see_new_subclass(classdef) + + def read_attr__class__(self): + position = self.bookkeeper.position_key + self.read_locations_of__class__[position] = True + return SomePBC([subdef.classdesc for subdef in self.getallsubdefs()]) + def _freeze_(self): raise Exception, "ClassDefs are used as knowntype for instances but cannot be used as immutablevalue arguments directly" Modified: pypy/dist/pypy/annotation/test/test_annrpython.py ============================================================================== --- pypy/dist/pypy/annotation/test/test_annrpython.py (original) +++ pypy/dist/pypy/annotation/test/test_annrpython.py Fri May 5 10:55:40 2006 @@ -2035,7 +2035,31 @@ assert isinstance(s.items[0], annmodel.SomeInteger) assert isinstance(s.items[1], annmodel.SomeChar) assert isinstance(s.items[2], annmodel.SomeChar) - + + def test___class___attribute(self): + class Base(object): pass + class A(Base): pass + class B(Base): pass + class C(A): pass + def seelater(): + C() + def f(n): + if n == 1: + x = A() + else: + x = B() + y = B() + result = x.__class__, y.__class__ + seelater() + return result + + a = self.RPythonAnnotator() + s = a.build_types(f, [int]) + assert isinstance(s.items[0], annmodel.SomePBC) + assert len(s.items[0].descriptions) == 4 + assert isinstance(s.items[1], annmodel.SomePBC) + assert len(s.items[1].descriptions) == 1 + def g(n): return [0,1,2,n] Modified: pypy/dist/pypy/annotation/unaryop.py ============================================================================== --- pypy/dist/pypy/annotation/unaryop.py (original) +++ pypy/dist/pypy/annotation/unaryop.py Fri May 5 10:55:40 2006 @@ -467,6 +467,8 @@ def getattr(ins, s_attr): if s_attr.is_constant() and isinstance(s_attr.const, str): attr = s_attr.const + if attr == '__class__': + return ins.classdef.read_attr__class__() attrdef = ins.classdef.find_attribute(attr) position = getbookkeeper().position_key attrdef.read_locations[position] = True Modified: pypy/dist/pypy/rpython/lltypesystem/rclass.py ============================================================================== --- pypy/dist/pypy/rpython/lltypesystem/rclass.py (original) +++ pypy/dist/pypy/rpython/lltypesystem/rclass.py Fri May 5 10:55:40 2006 @@ -519,6 +519,10 @@ def rtype_getattr(self, hop): attr = hop.args_s[1].const vinst, vattr = hop.inputargs(self, Void) + if attr == '__class__' and hop.r_result.lowleveltype is Void: + # special case for when the result of '.__class__' is a constant + [desc] = hop.s_result.descriptions + return hop.inputconst(Void, desc.pyobj) if attr in self.allinstancefields: return self.getfield(vinst, attr, hop.llops) elif attr in self.rclass.allmethods: Modified: pypy/dist/pypy/rpython/ootypesystem/rclass.py ============================================================================== --- pypy/dist/pypy/rpython/ootypesystem/rclass.py (original) +++ pypy/dist/pypy/rpython/ootypesystem/rclass.py Fri May 5 10:55:40 2006 @@ -355,6 +355,15 @@ cname = hop.inputconst(ootype.Void, mangled) return hop.genop("oosend", [cname, v_inst], resulttype = hop.r_result.lowleveltype) + elif attr == '__class__': + if hop.r_result.lowleveltype is ootype.Void: + # special case for when the result of '.__class__' is constant + [desc] = hop.s_result.descriptions + return hop.inputconst(ootype.Void, desc.pyobj) + else: + cmeta = inputconst(ootype.Void, "meta") + return hop.genop('oogetfield', [v_inst, cmeta], + resulttype=CLASSTYPE) else: raise TyperError("no attribute %r on %r" % (attr, self)) 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 May 5 10:55:40 2006 @@ -463,6 +463,30 @@ res = interpret(f, [], type_system=self.ts) assert typeOf(res.item0) == Signed + def test___class___attribute(self): + class Base(object): pass + class A(Base): pass + class B(Base): pass + class C(A): pass + def seelater(): + C() + def f(n): + if n == 1: + x = A() + else: + x = B() + y = B() + result = x.__class__, y.__class__ + seelater() + return result + def g(): + cls1, cls2 = f(1) + return cls1 is A, cls2 is B + + res = interpret(g, [], type_system=self.ts) + assert res.item0 + assert res.item1 + class TestLltype(BaseTestRclass): From arigo at codespeak.net Fri May 5 14:38:19 2006 From: arigo at codespeak.net (arigo at codespeak.net) Date: Fri, 5 May 2006 14:38:19 +0200 (CEST) Subject: [pypy-svn] r26812 - in pypy/dist/pypy: interpreter module/_weakref/test objspace/std Message-ID: <20060505123819.D58AC10092@code0.codespeak.net> Author: arigo Date: Fri May 5 14:38:18 2006 New Revision: 26812 Modified: pypy/dist/pypy/interpreter/baseobjspace.py pypy/dist/pypy/interpreter/typedef.py pypy/dist/pypy/module/_weakref/test/test_weakref.py pypy/dist/pypy/objspace/std/typeobject.py pypy/dist/pypy/objspace/std/typetype.py Log: WeakrefableMixin causes trouble: in general we assume that mixins are not before the normal base class. Factored it out in a way that still allows a nice implementation of weakrefable built-in objects. Made functions, methods and generators weakrefable. Modified: pypy/dist/pypy/interpreter/baseobjspace.py ============================================================================== --- pypy/dist/pypy/interpreter/baseobjspace.py (original) +++ pypy/dist/pypy/interpreter/baseobjspace.py Fri May 5 14:38:18 2006 @@ -7,8 +7,7 @@ from pypy.rpython.rarithmetic import r_uint, intmask import os -__all__ = ['ObjSpace', 'OperationError', 'Wrappable', 'W_Root', - 'WeakrefableMixin'] +__all__ = ['ObjSpace', 'OperationError', 'Wrappable', 'W_Root'] class W_Root(object): @@ -78,16 +77,6 @@ def __spacebind__(self, space): return self -class WeakrefableMixin(object): - _mixin_ = True - __lifeline__ = None - - def getweakref(self): - return self.__lifeline__ - - def setweakref(self, space, weakreflifeline): - self.__lifeline__ = weakreflifeline - class InternalSpaceCache(Cache): """A generic cache for an object space. Arbitrary information can be attached to the space by defining a function or class 'f' which Modified: pypy/dist/pypy/interpreter/typedef.py ============================================================================== --- pypy/dist/pypy/interpreter/typedef.py (original) +++ pypy/dist/pypy/interpreter/typedef.py Fri May 5 14:38:18 2006 @@ -5,7 +5,7 @@ import py from pypy.interpreter.gateway import interp2app from pypy.interpreter.argument import Arguments -from pypy.interpreter.baseobjspace import Wrappable, W_Root, ObjSpace, WeakrefableMixin +from pypy.interpreter.baseobjspace import Wrappable, W_Root, ObjSpace from pypy.interpreter.error import OperationError from pypy.tool.sourcetools import compile2 from pypy.rpython.objectmodel import instantiate @@ -16,8 +16,10 @@ self.name = __name self.base = __base self.hasdict = '__dict__' in rawdict + self.weakrefable = '__weakref__' in rawdict if __base is not None: self.hasdict |= __base.hasdict + self.weakrefable |= __base.weakrefable self.rawdict = {} self.acceptable_as_base_class = True # xxx used by faking @@ -38,7 +40,6 @@ def get_unique_interplevel_subclass(cls, hasdict, wants_slots, needsdel=False, weakrefable=False): - weakrefable = weakrefable and not issubclass(cls, WeakrefableMixin) key = cls, hasdict, wants_slots, needsdel, weakrefable try: return _subclass_cache[key] @@ -54,8 +55,10 @@ typedef = cls.typedef if hasdict and typedef.hasdict: - return get_unique_interplevel_subclass(cls, False, wants_slots, wants_del, weakrefable) - + hasdict = False + if weakrefable and typedef.weakrefable: + weakrefable = False + name = ['User'] if not hasdict: name.append('NoDict') @@ -69,7 +72,16 @@ name.append(cls.__name__) name = ''.join(name) - if wants_del: + if weakrefable: + supercls = get_unique_interplevel_subclass(cls, hasdict, wants_slots, + wants_del, False) + class Proto(object): + _lifeline_ = None + def getweakref(self): + return self._lifeline_ + def setweakref(self, space, weakreflifeline): + self._lifeline_ = weakreflifeline + elif wants_del: supercls = get_unique_interplevel_subclass(cls, hasdict, wants_slots, False, False) parent_destructor = getattr(cls, '__del__', None) @@ -135,13 +147,8 @@ body = dict([(key, value) for key, value in Proto.__dict__.items() - if not key.startswith('_') or key == '__del__']) - - if weakrefable and not issubclass(supercls, WeakrefableMixin): - subcls = type(name, (WeakrefableMixin, supercls), body) - else: - subcls = type(name, (supercls,), body) - + if not key.startswith('__') or key == '__del__']) + subcls = type(name, (supercls,), body) return subcls def make_descr_typecheck_wrapper(func, extraargs=(), cls=None): @@ -414,6 +421,17 @@ weakref_descr = GetSetProperty(descr_get_weakref) weakref_descr.name = '__weakref__' +def make_weakref_descr(cls): + # force the interface into the given cls + def getweakref(self): + return self._lifeline_ + def setweakref(self, space, weakreflifeline): + self._lifeline_ = weakreflifeline + cls._lifeline_ = None + cls.getweakref = getweakref + cls.setweakref = setweakref + return weakref_descr + Code.typedef = TypeDef('internal-code', co_name = interp_attrproperty('co_name', cls=Code), @@ -516,6 +534,7 @@ __name__ = getset_func_name, __dict__ = getset_func_dict, __module__ = getset___module__, + __weakref__ = make_weakref_descr(Function), # XXX func_closure, etc.pp ) @@ -533,6 +552,7 @@ __repr__ = interp2app(Method.descr_method_repr), __reduce__ = interp2app(Method.descr_method__reduce__, unwrap_spec=['self', ObjSpace]), + __weakref__ = make_weakref_descr(Method), # XXX getattribute/setattribute etc.pp ) @@ -563,6 +583,7 @@ __iter__ = interp2app(GeneratorIterator.descr__iter__), gi_running = interp_attrproperty('running', cls=GeneratorIterator), gi_frame = interp_attrproperty('frame', cls=GeneratorIterator), + __weakref__ = make_weakref_descr(GeneratorIterator), ) Cell.typedef = TypeDef("cell", Modified: pypy/dist/pypy/module/_weakref/test/test_weakref.py ============================================================================== --- pypy/dist/pypy/module/_weakref/test/test_weakref.py (original) +++ pypy/dist/pypy/module/_weakref/test/test_weakref.py Fri May 5 14:38:18 2006 @@ -169,32 +169,32 @@ assert b.a == 42 def test_function_weakrefable(self): - skip("wip") import _weakref def f(x): return 42 wf = _weakref.ref(f) - assert wf()() == 42 + assert wf()(63) == 42 del f assert wf() is None def test_method_weakrefable(self): - skip("wip") import _weakref class A(object): def f(self): return 42 a = A() - w_unbound = _weakref.ref(A.f) + meth = A.f + w_unbound = _weakref.ref(meth) assert w_unbound()(A()) == 42 - w_bound = _weakref.ref(A().f) + meth = A().f + w_bound = _weakref.ref(meth) assert w_bound()() == 42 - del A + del meth assert w_unbound() is None assert w_bound() is None def test_set_weakrefable(self): - skip("wip") + skip("missing: weakrefs to interp-level sets") import _weakref s = set([1, 2, 3, 4]) w = _weakref.ref(s) @@ -203,11 +203,10 @@ assert w() is None def test_generator_weakrefable(self): - skip("wip") import _weakref def f(x): for i in range(x): - yield x + yield i g = f(10) w = _weakref.ref(g) r = w().next() Modified: pypy/dist/pypy/objspace/std/typeobject.py ============================================================================== --- pypy/dist/pypy/objspace/std/typeobject.py (original) +++ pypy/dist/pypy/objspace/std/typeobject.py Fri May 5 14:38:18 2006 @@ -2,7 +2,7 @@ from pypy.interpreter.function import Function, StaticMethod from pypy.interpreter.argument import Arguments from pypy.interpreter import gateway -from pypy.interpreter.typedef import WeakrefableMixin, weakref_descr +from pypy.interpreter.typedef import weakref_descr from pypy.objspace.std.stdtypedef import std_dict_descr, issubtypedef, Member from pypy.objspace.std.objecttype import object_typedef from pypy.objspace.std.dictproxyobject import W_DictProxyObject @@ -38,7 +38,7 @@ return "_%s%s" % (klass, name) -class W_TypeObject(WeakrefableMixin, W_Object): +class W_TypeObject(W_Object): from pypy.objspace.std.typetype import type_typedef as typedef lazyloaders = {} # can be overridden by specific instances @@ -52,7 +52,6 @@ w_self.ensure_static__new__() w_self.nslots = 0 w_self.needsdel = False - w_self.weakrefable = False w_self.w_bestbase = None # make sure there is a __doc__ in dict_w @@ -62,6 +61,7 @@ if overridetypedef is not None: w_self.instancetypedef = overridetypedef w_self.hasdict = overridetypedef.hasdict + w_self.weakrefable = overridetypedef.weakrefable w_self.__flags__ = 0 # not a heaptype if overridetypedef.base is not None: w_self.w_bestbase = space.gettypeobject(overridetypedef.base) @@ -102,6 +102,7 @@ instancetypedef.name)) w_self.instancetypedef = instancetypedef w_self.hasdict = False + w_self.weakrefable = False hasoldstylebase = False w_most_derived_base_with_slots = None w_newstyle = None @@ -171,7 +172,7 @@ space.wrap("__dict__ slot disallowed: we already got one")) wantdict = True elif slot_name == '__weakref__': - if w_self.weakrefable: + if wantweakref or w_self.weakrefable: raise OperationError(space.w_TypeError, space.wrap("__weakref__ slot disallowed: we already got one")) @@ -313,7 +314,14 @@ return w_self.dict_w['__module__'] else: return space.wrap('__builtin__') - + + # for now, weakref support for W_TypeObject is hard to get automatically + _lifeline_ = None + def getweakref(self): + return self._lifeline_ + def setweakref(self, space, weakreflifeline): + self._lifeline_ = weakreflifeline + def call__Type(space, w_type, __args__): # special case for type(x) Modified: pypy/dist/pypy/objspace/std/typetype.py ============================================================================== --- pypy/dist/pypy/objspace/std/typetype.py (original) +++ pypy/dist/pypy/objspace/std/typetype.py Fri May 5 14:38:18 2006 @@ -1,5 +1,6 @@ from pypy.interpreter.error import OperationError from pypy.interpreter import gateway +from pypy.interpreter.typedef import weakref_descr from pypy.objspace.std.stdtypedef import * def descr__new__(space, w_typetype, w_name, w_bases, w_dict): @@ -150,4 +151,5 @@ mro = gateway.interp2app(descr_mro), __flags__ = GetSetProperty(descr__flags), __module__ = GetSetProperty(descr_get__module, descr_set__module), + __weakref__ = weakref_descr, ) From bea at codespeak.net Fri May 5 14:42:59 2006 From: bea at codespeak.net (bea at codespeak.net) Date: Fri, 5 May 2006 14:42:59 +0200 (CEST) Subject: [pypy-svn] r26813 - pypy/extradoc/talk/agile2006 Message-ID: <20060505124259.A4D8210092@code0.codespeak.net> Author: bea Date: Fri May 5 14:42:57 2006 New Revision: 26813 Modified: pypy/extradoc/talk/agile2006/draftpaper_agile2006.txt Log: tuning.. Modified: pypy/extradoc/talk/agile2006/draftpaper_agile2006.txt ============================================================================== --- pypy/extradoc/talk/agile2006/draftpaper_agile2006.txt (original) +++ pypy/extradoc/talk/agile2006/draftpaper_agile2006.txt Fri May 5 14:42:57 2006 @@ -18,7 +18,7 @@ the Python community evolved technique of "sprinting") and the EU funding practices (resource tracking and reporting) impacting the project. These influencing factors laid the foundation for the custom-made project process -that makes this unique hybrid project work and the main factor for driving this +that makes this unique hybrid project work. The main factor for driving this process is the skills of the team of core developers instigating the project. PyPy, with its open and transparent communication and collaborative work style, is again a proof that the best agile practice is the people factor. @@ -44,12 +44,12 @@ the Open Source project applied for EU-funding. Today the project has over 4 years of intense activity as an Open Source -community (F/OSS) effort and have completed a successful first year of the -EU-funded effort. In order to understand how the PyPy project -manages to strike a balance between being an F/OSS community, while also having -the core work of the project being funded by the European Union (with all the -structure and process requirements that entails) we need to look at the -influencing factors of the project process. +community (F/OSS, Free Open Source Software) effort and have completed a +successful first year of the EU-funded effort. In order to understand how the +PyPy project manages to strike a balance between being an F/OSS community, +while also having the core work of the project being funded by the European +Union (with all the structure and process requirements that entails) we need to +look at the influencing factors of the project process. The influencing factors of the PyPy project process are: @@ -88,7 +88,7 @@ order to mitigate this risk. Our conclusion so far in the project is that we believe that the practice of -"sprinting", as being used in the PyPy project, makes Agile and +sprint-driven development, as being used in the PyPy project, makes Agile and Distributed/dispersed work styles more possible to combine. We also believe it is a very useful practice for creating value and ensuring quality in projects with hybrid cultures and methodologies. It is our aim to start to show-case @@ -246,7 +246,8 @@ was a stable subscriber participation on the development list of between 140-150 people. After the EU-funding and the more systematic structure of sprinting every 6th week the amount of subscribers went from around 150 people to -over 250 people. +over 250 people. Thus turning the prior experience of separate sprints into +a more systematic approach, sprint-driven development. Supporting infrastructure @@ -467,12 +468,12 @@ is a great way of getting results and getting new people acquainted - a good method for dissemination of knowledge and learning within the team. -A key insight, worthwhile for other EU-projects to ponder, is how an agile -process like sprinting is much more suited for creative work between groups of -distributed people. Traditional software development, as well as traditional -project management techniques have a tendency to hinder creativity due to the -inbuilt over-structured, segmented and control-oriented approach which in most -cases ends in less quality when results are being measured. +Another insight, worthwhile for other more discipline based projects to ponder, +is how an agile process like sprinting is much more suited for creative work +between groups of distributed people. Traditional software development, as well +as traditional project management techniques have a tendency to hinder creativity +due to the inbuilt over-structured, segmented and control-oriented approach +which in most cases ends in less quality when results are being measured. EU-project practices ==================== @@ -534,7 +535,7 @@ All documentation and supporting communication infrastructure is hosted on the same developer server as the source code, covered by the same version control -system. Only a few repositories are not public available (such as the resource +system. Only a few repositories are not publically available (such as the resource tracking repositories) - but they are fully accessible for everyone employed by a partner organization. From ale at codespeak.net Fri May 5 16:46:54 2006 From: ale at codespeak.net (ale at codespeak.net) Date: Fri, 5 May 2006 16:46:54 +0200 (CEST) Subject: [pypy-svn] r26818 - pypy/dist/pypy/lib/pyontology/test Message-ID: <20060505144654.1BDCB10092@code0.codespeak.net> Author: ale Date: Fri May 5 16:46:53 2006 New Revision: 26818 Added: pypy/dist/pypy/lib/pyontology/test/conclusions001.rdf (contents, props changed) pypy/dist/pypy/lib/pyontology/test/conclusions003.rdf (contents, props changed) pypy/dist/pypy/lib/pyontology/test/premises001.rdf (contents, props changed) pypy/dist/pypy/lib/pyontology/test/premises003.rdf (contents, props changed) Modified: pypy/dist/pypy/lib/pyontology/test/test_ontology.py Log: A litle progress on terminology checking Added: pypy/dist/pypy/lib/pyontology/test/conclusions001.rdf ============================================================================== --- (empty file) +++ pypy/dist/pypy/lib/pyontology/test/conclusions001.rdf Fri May 5 16:46:53 2006 @@ -0,0 +1,43 @@ + + + + + + + + + + + 1 + + + + + + 1 + + + + + Added: pypy/dist/pypy/lib/pyontology/test/conclusions003.rdf ============================================================================== --- (empty file) +++ pypy/dist/pypy/lib/pyontology/test/conclusions003.rdf Fri May 5 16:46:53 2006 @@ -0,0 +1,43 @@ + + + + + + + + + + + 2 + + + + + + 2 + + + + + Added: pypy/dist/pypy/lib/pyontology/test/premises001.rdf ============================================================================== --- (empty file) +++ pypy/dist/pypy/lib/pyontology/test/premises001.rdf Fri May 5 16:46:53 2006 @@ -0,0 +1,35 @@ + + + + + + + + + + + 1 + + + + + Added: pypy/dist/pypy/lib/pyontology/test/premises003.rdf ============================================================================== --- (empty file) +++ pypy/dist/pypy/lib/pyontology/test/premises003.rdf Fri May 5 16:46:53 2006 @@ -0,0 +1,35 @@ + + + + + + + + + + + 2 + + + + + Modified: pypy/dist/pypy/lib/pyontology/test/test_ontology.py ============================================================================== --- pypy/dist/pypy/lib/pyontology/test/test_ontology.py (original) +++ pypy/dist/pypy/lib/pyontology/test/test_ontology.py Fri May 5 16:46:53 2006 @@ -39,9 +39,9 @@ def test_subClassof(): O = Ontology() - a = URIRef(u'A') - b = URIRef(u'B') - c = URIRef(u'C') + a = O.make_var(ClassDomain,URIRef(u'A')) + b = O.make_var(ClassDomain,URIRef(u'B')) + c = O.make_var(ClassDomain,URIRef(u'C')) O.subClassOf(b, a) O.subClassOf(c, b) obj = URIRef(namespaces['owl']+'#Class') @@ -104,10 +104,10 @@ assert 'a' in c.getValues() def test_equivalentClass(): - a = URIRef('A') - b = URIRef('B') - c = URIRef('C') O = Ontology() + a = O.make_var(ClassDomain,URIRef('A')) + b = O.make_var(ClassDomain,URIRef('B')) + c = O.make_var(ClassDomain,URIRef('C')) O.equivalentClass(c, a) O.equivalentClass(c, b) A = O.make_var(ClassDomain, a) @@ -507,13 +507,13 @@ # predicate p O = Ontology() - cls = URIRef('cls') + cls = O.make_var(ClassDomain,URIRef('cls')) O.type(cls, namespaces['owl']+'#Class') - p = URIRef('p') + p = O.make_var(Property,URIRef('p')) O.type(p, namespaces['owl']+'#ObjectProperty') - restr = BNode('anon') + restr = O.make_var(Restriction,BNode('anon')) O.subClassOf(cls, restr) O.maxCardinality(restr, 2) O.type(restr, namespaces['owl']+'#Restriction') @@ -526,7 +526,28 @@ O.minCardinality(restr2, 3) constraints = len(O.constraints) py.test.raises(ConsistencyFailure, O.consistency, 3) - - assert 0 - +def test_add_file(): + O = Ontology() + O.add_file('premises001.rdf') + trip = list(O.graph.triples((None,)*3)) + O.attach_fd() + ll = len(O.variables) + l = len(trip) + O.add_file('conclusions001.rdf') + O.attach_fd() + lll = len(O.variables) + assert len(list(O.graph.triples((None,)*3))) > l + +def test_more_cardinality(): + O = Ontology() + O.add_file('premises003.rdf') + trip = list(O.graph.triples((None,)*3)) + O.attach_fd() + ll = len(O.variables) + l = len(trip) + O.add_file('conclusions003.rdf') + O.attach_fd() + O.check_TBoxes() + lll = len(O.variables) + assert len(list(O.graph.triples((None,)*3))) > l From dialtone at codespeak.net Fri May 5 17:22:35 2006 From: dialtone at codespeak.net (dialtone at codespeak.net) Date: Fri, 5 May 2006 17:22:35 +0200 (CEST) Subject: [pypy-svn] r26819 - pypy/dist/pypy/translator/cl Message-ID: <20060505152235.6D4A61009D@code0.codespeak.net> Author: dialtone Date: Fri May 5 17:22:34 2006 New Revision: 26819 Modified: pypy/dist/pypy/translator/cl/gencl.py pypy/dist/pypy/translator/cl/opformatter.py Log: actually support dictionary iterator in a lisp-portable way, unfortunately it's currently a work-around waiting for a better solution Modified: pypy/dist/pypy/translator/cl/gencl.py ============================================================================== --- pypy/dist/pypy/translator/cl/gencl.py (original) +++ pypy/dist/pypy/translator/cl/gencl.py Fri May 5 17:22:34 2006 @@ -67,6 +67,26 @@ self.structcount += 1 return name + def declare_dict_iter(self): + name = 'pypy-dict-iter' + if name in self.declarations: + return self.declarations[name][0] + definition = """\ +(defun %s (hash) + (let ((current-index -1) + (keys (loop for keys being the hash-keys in hash collect keys))) + (cons (lambda () + (let ((more (<= (incf current-index) (1- (length keys))))) + (if more + (let* ((key (nth current-index keys)) + (val (gethash key hash))) + (values more key val)) + (values nil nil nil)))) + (lambda () + (nth current-index keys)))))""" % (name) + self.declarations[name] = (name, definition) + return name + def declare_class(self, cls): assert isinstance(cls, Instance) assert not self.is_exception_instance(cls) Modified: pypy/dist/pypy/translator/cl/opformatter.py ============================================================================== --- pypy/dist/pypy/translator/cl/opformatter.py (original) +++ pypy/dist/pypy/translator/cl/opformatter.py Fri May 5 17:22:34 2006 @@ -115,7 +115,7 @@ code = getattr(impl, method)(*args) yield "(setf %s %s)" % (result, code) elif isinstance(cls, Dict): - impl = DictImpl(selfvar) + impl = DictImpl(selfvar, self.gen) code = getattr(impl, method)(*args) yield "(setf %s %s)" % (result, code) elif isinstance(cls, DictItemsIterator): @@ -131,7 +131,7 @@ def op_oogetfield(self, result, obj, _): fieldname = self.args[1].value - if isinstance(self.args[0].concretetype, Record): + if isinstance(self.args[0].concretetype, Record): yield "(setf %s (slot-value %s '%s))" % (clrepr(result, True), clrepr(obj, True), clrepr(fieldname, True)) @@ -184,8 +184,9 @@ class DictImpl: - def __init__(self, obj): + def __init__(self, obj, gen): self.obj = obj + self.gen = gen def ll_length(self): return "(hash-table-count %s)" % (self.obj,) @@ -202,11 +203,8 @@ def ll_get_items_iterator(self): # This is explicitly unspecified by the specification. # Should think of a better way to do this. - return """\ -(let ((temp (gensym))) - (setf (symbol-value temp) - (with-hash-table-iterator (iter %s) - (lambda () (iter)))) temp)""" % (self.obj,) + name = self.gen.declare_dict_iter() + return "(%s %s)" % (name, self.obj) class DictItemsIteratorImpl: @@ -216,10 +214,8 @@ def ll_go_next(self): return """\ (multiple-value-bind (more key value) - (funcall (symbol-value %s)) - (setf (get %s 'key) key) - (setf (get %s 'value) value) - more)""" % (self.obj, self.obj, self.obj) + (funcall (car %s)) + more)""" % (self.obj,) def ll_current_key(self): - return "(get %s 'key)" % (self.obj,) + return "(funcall (cdr %s))" % (self.obj,) From ale at codespeak.net Fri May 5 18:17:12 2006 From: ale at codespeak.net (ale at codespeak.net) Date: Fri, 5 May 2006 18:17:12 +0200 (CEST) Subject: [pypy-svn] r26820 - pypy/dist/pypy/lib/pyontology Message-ID: <20060505161712.ACF62100A7@code0.codespeak.net> Author: ale Date: Fri May 5 18:17:11 2006 New Revision: 26820 Modified: pypy/dist/pypy/lib/pyontology/pyontology.py Log: Forgot to check this in - sorry Modified: pypy/dist/pypy/lib/pyontology/pyontology.py ============================================================================== --- pypy/dist/pypy/lib/pyontology/pyontology.py (original) +++ pypy/dist/pypy/lib/pyontology/pyontology.py Fri May 5 18:17:11 2006 @@ -37,6 +37,7 @@ else: format = "n3" return format + class ClassDomain(AbstractDomain): # Class domain is intended as a (abstract/virtual) domain for implementing @@ -220,6 +221,7 @@ def __init__(self, store = 'default'): self.graph = Graph(store) + self.store = store if store != 'default': self.graph.open(py.path.local().join("db").strpath) self.variables = {} @@ -229,19 +231,26 @@ def add(self, triple): self.graph.add(triple) - + def add_file(self, f, format=None): + tmp = Graph('default') + tmp.load(f, format) + for triple in tmp.triples((None,)*3): + self.add(triple) + + def load_file(self, f, format=None): if not format: format = check_format(f) self.graph.load(f, format=format) def attach_fd(self): for (s, p, o) in (self.graph.triples((None,)*3)): - if (s, p, o) in self.seen: + if (s, p, o) in self.seen.keys(): continue self.seen[(s, p, o)] = True self.consider_triple((s, p, o)) - + assert len(list(self.graph.triples((None,)*3))) == len(self.seen.keys()) + def consider_triple(self,(s, p, o)): if p.find('#') != -1: ns, func = p.split('#') @@ -252,10 +261,6 @@ #predicate is one of builtin OWL or rdf predicates pred = getattr(self, func) res = pred(s, o) - if not res : - return - if type(res) != list : - res = [res] avar = self.make_var(ClassDomain, s) else: avar = self.make_var(Property, p) @@ -265,6 +270,32 @@ propdom = self.variables[avar] res = propdom.addValue(sub, obj) + def evaluate(self, terms): + # terms is a dictionary of types of restriction and list of values for this restriction + term = terms['Cardinality'] + if len(term) < 1: return + mini = maxi = equal = None + + for tp,val in term: + if tp == '<': + if not maxi or val < maxi : maxi = val + elif tp == '>': + if not mini or val > mini : mini = val + else: + if equal: + raise ConsistencyFailure + equal = val + + if mini and maxi and (mini > maxi or + equal < mini or + equal > maxi): + raise ConsistencyFailure + + def check_TBoxes(self): + for var, cls in self.variables.items(): + for prop, terms in cls.TBox.items(): + if len(terms) > 1: + self.evaluate(terms) def solve(self,verbose=0): rep = Repository(self.variables.keys(), self.variables, self.constraints) @@ -299,12 +330,13 @@ def resolve_item(self, item): item_as_subject = self.graph.triples((item, None, None)) for triple in item_as_subject: - if triple in self.seen: + if triple in self.seen.keys(): continue self.seen[triple] = True self.consider_triple(triple) def make_var(self, cls=fd, a=''): + self.resolve_item(a) if type(a) == URIRef: if a.find('#') != -1: ns,name = a.split('#') @@ -374,6 +406,17 @@ # var avar = self.make_var(None, var) svar = self.make_var(ClassDomain, s) + obj = self.variables[avar] + sub = self.variables[svar] + if obj.TBox: + sub.TBox.setdefault(obj.property, {}) + op = sub.TBox[obj.property] + for restr in obj.TBox.keys(): + op.setdefault(restr,[]) + op[restr].extend(obj.TBox[restr]) + + assert len(sub.TBox) > 0 +# self.variables.pop(avar) cons = SubClassConstraint( svar, avar) self.constraints.append(cons) @@ -467,22 +510,14 @@ svar =self.make_var(Restriction, s) constrain = MaxCardinality(svar, int(var)) self.constraints.append(constrain) - # Make a new variable that can hold the domain of possible cardinality - # values - self.variables[svar].TBox['Cardinality'] = (range( int(var)+1), 'in') -# var_name = '%s_Cardinality' % svar -# self.variables[var_name] = fd(range(int(var)+1)) + self.variables[svar].TBox['Cardinality'] = [( '>', int(var))] def minCardinality(self, s, var): """ Len of finite domain of the property shall be greater than or equal to var""" svar =self.make_var(Restriction, s) constrain = MinCardinality(svar, int(var)) self.constraints.append(constrain) - self.variables[svar].TBox['Cardinality'] = ( range(int(var)), 'not in') -# var_name = '%s_Cardinality' % svar -# self.variables[var_name] = fd(range(int(var))) -# constraint = Expression(var_name,' not in') -# self.constraints.append(constraint) + self.variables[svar].TBox['Cardinality'] = [( '>', int(var))] def cardinality(self, s, var): """ Len of finite domain of the property shall be equal to var""" @@ -490,33 +525,7 @@ # Check if var is an int, else find the int buried in the structure constrain = Cardinality(svar, int(var)) self.constraints.append(constrain) - self.variables[svar].TBox['Cardinality'] = ( [int(var)], 'in') -# var_name = '%s_Cardinality' % svar -# self.variables['var_name'] = fd(int(var)) - - def differentFrom(self, s, var): - s_var = self.make_var(Thing, s) - var_var = self.make_var(Thing, var) - constrain = DifferentfromConstraint(s_var, var_var) - self.constraints.append(constrain) - -#XXX need to change this - def distinctMembers(self, s, var): - s_var = self.make_var(AllDifferent, s) - var_var = self.flatten_rdf_list(var) - #var_var = self.make_var(List, var) - for v in var_var: - indx = var_var.index(v) - for other in var_var[indx+1:]: - self.differentFrom(v, other) - constrain = AllDifferentConstraint(s_var, var_var) - self.constraints.append(constrain) - - def sameAs(self, s, var): - s_var = self.make_var(None, s) - var_var = self.make_var(None, var) - constrain = SameasConstraint(s_var, var_var) - self.constraints.append(constrain) + self.variables[svar].TBox['Cardinality'] = [( '=', int(var))] def hasValue(self, s, var): svar = self.make_var(Restriction, s) @@ -535,9 +544,35 @@ avar = self.make_var(None, var) constrain = SomeValueConstraint(svar, avar) self.constraints.append(constrain) + +# ----------------- ---------------- def imports(self, s, var): # PP TODO: implement this pass -# ----------------- Helper classes ---------------- + def sameAs(self, s, var): + s_var = self.make_var(Thing, s) + var_var = self.make_var(Thing, var) + constrain = SameasConstraint(s_var, var_var) + self.constraints.append(constrain) + + + def differentFrom(self, s, var): + s_var = self.make_var(Thing, s) + var_var = self.make_var(Thing, var) + constrain = DifferentfromConstraint(s_var, var_var) + self.constraints.append(constrain) + +#XXX need to change this + def distinctMembers(self, s, var): + s_var = self.make_var(AllDifferent, s) + var_var = self.flatten_rdf_list(var) + #var_var = self.make_var(List, var) + for v in var_var: + indx = var_var.index(v) + for other in var_var[indx+1:]: + self.differentFrom(v, other) + constrain = AllDifferentConstraint(s_var, var_var) + self.constraints.append(constrain) + From arigo at codespeak.net Fri May 5 19:29:44 2006 From: arigo at codespeak.net (arigo at codespeak.net) Date: Fri, 5 May 2006 19:29:44 +0200 (CEST) Subject: [pypy-svn] r26822 - in pypy/dist/pypy: annotation rpython rpython/lltypesystem rpython/ootypesystem rpython/test Message-ID: <20060505172944.A642910092@code0.codespeak.net> Author: arigo Date: Fri May 5 19:29:42 2006 New Revision: 26822 Modified: pypy/dist/pypy/annotation/bookkeeper.py pypy/dist/pypy/annotation/description.py pypy/dist/pypy/rpython/lltypesystem/rclass.py pypy/dist/pypy/rpython/lltypesystem/rpbc.py pypy/dist/pypy/rpython/normalizecalls.py pypy/dist/pypy/rpython/ootypesystem/rclass.py pypy/dist/pypy/rpython/rpbc.py pypy/dist/pypy/rpython/test/test_rpbc.py Log: Half refactoring of the AttrFamily: it is unchanged for FrozenDescs, but for ClassDescs it now records attribute access for each attribute name independently. See new test in test_rpbc. This is prompted by PyPy translation crashes: introducing a memo function on the pbc of all W_Root subclasses forced them to be all in the same AttrFamily, which had terribly bad effects, as follows: a few subclasses of ast.Node are instantiated generically (by calling a variable that can be any of them). The same is true for the subclasses of PyFrame. However, the __init__ in these two parts of the hierarchy are completely different. So any common pbc attribute on all W_Root subclasses caused the __init__ to come together too => obsure crash. Modified: pypy/dist/pypy/annotation/bookkeeper.py ============================================================================== --- pypy/dist/pypy/annotation/bookkeeper.py (original) +++ pypy/dist/pypy/annotation/bookkeeper.py Fri May 5 19:29:42 2006 @@ -165,7 +165,8 @@ self.dictdefs = {} # map position_keys to DictDefs self.immutable_cache = {} - self.pbc_maximal_access_sets = UnionFind(description.AttrFamily) + self.classpbc_attr_families = {} # {'attr': UnionFind(ClassAttrFamily)} + self.frozenpbc_attr_families = UnionFind(description.FrozenAttrFamily) self.pbc_maximal_call_families = UnionFind(description.CallFamily) self.emulated_pbc_calls = {} @@ -533,6 +534,17 @@ o.knowntype = t return o + def get_classpbc_attr_families(self, attrname): + """Return the UnionFind for the ClassAttrFamilies corresponding to + attributes of the given name. + """ + map = self.classpbc_attr_families + try: + access_sets = map[attrname] + except KeyError: + access_sets = map[attrname] = UnionFind(description.ClassAttrFamily) + return access_sets + def pbc_getattr(self, pbc, s_attr): assert s_attr.is_constant() attr = s_attr.const @@ -541,8 +553,8 @@ if not descs: return SomeImpossibleValue() first = descs[0] - change = first.mergeattrfamilies(*descs[1:]) - attrfamily = first.getattrfamily() + change = first.mergeattrfamilies(descs[1:], attr) + attrfamily = first.getattrfamily(attr) position = self.position_key attrfamily.read_locations[position] = True @@ -552,8 +564,8 @@ actuals.append(desc.s_read_attribute(attr)) s_result = unionof(*actuals) - attrfamily.attrs[attr] = unionof(s_result, - attrfamily.attrs.get(attr, s_ImpossibleValue)) + s_oldvalue = attrfamily.get_s_value(attr) + attrfamily.set_s_value(attr, unionof(s_result, s_oldvalue)) if change: for position in attrfamily.read_locations: Modified: pypy/dist/pypy/annotation/description.py ============================================================================== --- pypy/dist/pypy/annotation/description.py (original) +++ pypy/dist/pypy/annotation/description.py Fri May 5 19:29:42 2006 @@ -47,15 +47,15 @@ self.total_calltable_size += 1 -class AttrFamily: - """A family of Desc objects that have common 'getattr' sites. - The attr families are conceptually a partition of FrozenDesc and ClassDesc - objects, where the equivalence relation is the transitive closure of - 'd1~d2 if d1 and d2 might have an attribute read on them by the same - getattr operation.' +class FrozenAttrFamily: + """A family of FrozenDesc objects that have any common 'getattr' sites. + The attr families are conceptually a partition of FrozenDesc objects, + where the equivalence relation is the transitive closure of: + d1~d2 if d1 and d2 might have some attribute read on them by the same + getattr operation. """ def __init__(self, desc): - self.descs = { desc: True } + self.descs = {desc: True} self.read_locations = {} # set of position_keys self.attrs = {} # { attr: s_value } @@ -64,6 +64,49 @@ self.read_locations.update(other.read_locations) self.attrs.update(other.attrs) + def get_s_value(self, attrname): + try: + return self.attrs[attrname] + except KeyError: + from pypy.annotation.model import s_ImpossibleValue + return s_ImpossibleValue + + def set_s_value(self, attrname, s_value): + self.attrs[attrname] = s_value + + +class ClassAttrFamily: + """A family of ClassDesc objects that have common 'getattr' sites for a + given attribute name. The attr families are conceptually a partition + of ClassDesc objects, where the equivalence relation is the transitive + closure of: d1~d2 if d1 and d2 might have a common attribute 'attrname' + read on them by the same getattr operation. + + The 'attrname' is not explicitly stored here, but is the key used + in the dictionary bookkeeper.pbc_maximal_access_sets_map. + """ + # The difference between ClassAttrFamily and FrozenAttrFamily is that + # FrozenAttrFamily is the union for all attribute names, but + # ClassAttrFamily is more precise: it is only about one attribut name. + + def __init__(self, desc): + from pypy.annotation.model import s_ImpossibleValue + self.descs = { desc: True } + self.read_locations = {} # set of position_keys + self.s_value = s_ImpossibleValue # union of possible values + + def update(self, other): + from pypy.annotation.model import unionof + self.descs.update(other.descs) + self.read_locations.update(other.read_locations) + self.s_value = unionof(self.s_value, other.s_value) + + def get_s_value(self, attrname): + return self.s_value + + def set_s_value(self, attrname, s_value): + self.s_value = s_value + # ____________________________________________________________ class Desc(object): @@ -102,30 +145,6 @@ changed = changed or changed1 return changed - def getattrfamily(self): - """Get the AttrFamily object. Possibly creates one.""" - access_sets = self.bookkeeper.pbc_maximal_access_sets - _, _, attrfamily = access_sets.find(self) - return attrfamily - - def queryattrfamily(self): - """Retrieve the AttrFamily object if there is one, otherwise - return None.""" - access_sets = self.bookkeeper.pbc_maximal_access_sets - try: - return access_sets[self] - except KeyError: - return None - - def mergeattrfamilies(self, *others): - """Merge the attr families of the given Descs into one.""" - access_sets = self.bookkeeper.pbc_maximal_access_sets - changed, rep, attrfamily = access_sets.find(self) - for desc in others: - changed1, rep, attrfamily = access_sets.union(rep, desc) - changed = changed or changed1 - return changed - def bind_under(self, classdef, name): return self @@ -548,6 +567,30 @@ def rowkey(self): return self + def getattrfamily(self, attrname): + "Get the ClassAttrFamily object for attrname. Possibly creates one." + access_sets = self.bookkeeper.get_classpbc_attr_families(attrname) + _, _, attrfamily = access_sets.find(self) + return attrfamily + + def queryattrfamily(self, attrname): + """Retrieve the ClassAttrFamily object for attrname if there is one, + otherwise return None.""" + access_sets = self.bookkeeper.get_classpbc_attr_families(attrname) + try: + return access_sets[self] + except KeyError: + return None + + def mergeattrfamilies(self, others, attrname): + """Merge the attr families of the given Descs into one.""" + access_sets = self.bookkeeper.get_classpbc_attr_families(attrname) + changed, rep, attrfamily = access_sets.find(self) + for desc in others: + changed1, rep, attrfamily = access_sets.union(rep, desc) + changed = changed or changed1 + return changed + class MethodDesc(Desc): knowntype = types.MethodType @@ -664,6 +707,30 @@ raise AssertionError("name clash: %r" % (name,)) self.attrcache[name] = value + def getattrfamily(self, attrname=None): + "Get the FrozenAttrFamily object for attrname. Possibly creates one." + access_sets = self.bookkeeper.frozenpbc_attr_families + _, _, attrfamily = access_sets.find(self) + return attrfamily + + def queryattrfamily(self, attrname=None): + """Retrieve the FrozenAttrFamily object for attrname if there is one, + otherwise return None.""" + access_sets = self.bookkeeper.frozenpbc_attr_families + try: + return access_sets[self] + except KeyError: + return None + + def mergeattrfamilies(self, others, attrname=None): + """Merge the attr families of the given Descs into one.""" + access_sets = self.bookkeeper.frozenpbc_attr_families + changed, rep, attrfamily = access_sets.find(self) + for desc in others: + changed1, rep, attrfamily = access_sets.union(rep, desc) + changed = changed or changed1 + return changed + class MethodOfFrozenDesc(Desc): knowntype = types.MethodType Modified: pypy/dist/pypy/rpython/lltypesystem/rclass.py ============================================================================== --- pypy/dist/pypy/rpython/lltypesystem/rclass.py (original) +++ pypy/dist/pypy/rpython/lltypesystem/rclass.py Fri May 5 19:29:42 2006 @@ -114,12 +114,11 @@ # attributes showing up in getattrs done on the class as a PBC extra_access_sets = self.rtyper.class_pbc_attributes.get( self.classdef, {}) - for access_set, counter in extra_access_sets.items(): - for attr, s_value in access_set.attrs.items(): - r = self.rtyper.getrepr(s_value) - mangled_name = mangle('pbc%d' % counter, attr) - pbcfields[access_set, attr] = mangled_name, r - llfields.append((mangled_name, r.lowleveltype)) + for access_set, (attr, counter) in extra_access_sets.items(): + r = self.rtyper.getrepr(access_set.s_value) + mangled_name = mangle('pbc%d' % counter, attr) + pbcfields[access_set, attr] = mangled_name, r + llfields.append((mangled_name, r.lowleveltype)) # self.rbase = getclassrepr(self.rtyper, self.classdef.basedef) self.rbase.setup() Modified: pypy/dist/pypy/rpython/lltypesystem/rpbc.py ============================================================================== --- pypy/dist/pypy/rpython/lltypesystem/rpbc.py (original) +++ pypy/dist/pypy/rpython/lltypesystem/rpbc.py Fri May 5 19:29:42 2006 @@ -177,14 +177,14 @@ # instantiating a class from multiple possible classes from pypy.rpython.lltypesystem.rbuiltin import ll_instantiate vtypeptr = hop.inputarg(self, arg=0) - access_set = self.get_access_set() - r_class = self.get_class_repr() - if '__init__' in access_set.attrs: - s_init = access_set.attrs['__init__'] + try: + access_set, r_class = self.get_access_set('__init__') + except MissingRTypeAttribute: + s_init = annmodel.s_ImpossibleValue + else: + s_init = access_set.s_value v_init = r_class.getpbcfield(vtypeptr, access_set, '__init__', hop.llops) - else: - s_init = annmodel.s_ImpossibleValue v_inst1 = hop.gendirectcall(ll_instantiate, vtypeptr) v_instance = hop.genop('cast_pointer', [v_inst1], resulttype = r_instance) Modified: pypy/dist/pypy/rpython/normalizecalls.py ============================================================================== --- pypy/dist/pypy/rpython/normalizecalls.py (original) +++ pypy/dist/pypy/rpython/normalizecalls.py Fri May 5 19:29:42 2006 @@ -186,29 +186,30 @@ # PBC access set of the family of classes of 'some_class'. If the classes # have corresponding ClassDefs, they are not updated by the annotator. # We have to do it now. - access_sets = rtyper.annotator.bookkeeper.pbc_maximal_access_sets - for access_set in access_sets.infos(): - descs = access_set.descs - if len(descs) <= 1: - continue - if not isinstance(descs.iterkeys().next(), description.ClassDesc): - continue - classdefs = [desc.getuniqueclassdef() for desc in descs] - commonbase = classdefs[0] - for cdef in classdefs[1:]: - commonbase = commonbase.commonbase(cdef) - if commonbase is None: - raise TyperError("reading attributes %r: no common base class " - "for %r" % ( - access_set.attrs.keys(), descs.keys())) - extra_access_sets = rtyper.class_pbc_attributes.setdefault(commonbase, - {}) - if commonbase in rtyper.class_reprs: - assert access_set in extra_access_sets # minimal sanity check - return - access_set.commonbase = commonbase - if access_set not in extra_access_sets: - extra_access_sets[access_set] = len(extra_access_sets) + all_families = rtyper.annotator.bookkeeper.classpbc_attr_families + for attrname, access_sets in all_families.items(): + for access_set in access_sets.infos(): + descs = access_set.descs + if len(descs) <= 1: + continue + if not isinstance(descs.iterkeys().next(), description.ClassDesc): + continue + classdefs = [desc.getuniqueclassdef() for desc in descs] + commonbase = classdefs[0] + for cdef in classdefs[1:]: + commonbase = commonbase.commonbase(cdef) + if commonbase is None: + raise TyperError("reading attribute %r: no common base " + "class for %r" % (attrname, descs.keys())) + extra_access_sets = rtyper.class_pbc_attributes.setdefault( + commonbase, {}) + if commonbase in rtyper.class_reprs: + assert access_set in extra_access_sets # minimal sanity check + continue + access_set.commonbase = commonbase + if access_set not in extra_access_sets: + counter = len(extra_access_sets) + extra_access_sets[access_set] = attrname, counter # ____________________________________________________________ @@ -222,19 +223,17 @@ descs = family.descs.keys() if not isinstance(descs[0], description.ClassDesc): continue - # Note that a callfamily of classes must really be in the same - # attrfamily as well; This property is relied upon on various - # places in the rtyper - change = descs[0].mergeattrfamilies(*descs[1:]) + # Note that if classes are in the same callfamily, their __init__ + # attribute must be in the same attrfamily as well. + change = descs[0].mergeattrfamilies(descs[1:], '__init__') if hasattr(descs[0].getuniqueclassdef(), 'my_instantiate_graph'): assert not change, "after the fact change to a family of classes" # minimal sanity check return - attrfamily = descs[0].getattrfamily() # Put __init__ into the attr family, for ClassesPBCRepr.call() - s_value = attrfamily.attrs.get('__init__', annmodel.s_ImpossibleValue) + attrfamily = descs[0].getattrfamily('__init__') inits_s = [desc.s_read_attribute('__init__') for desc in descs] - s_value = annmodel.unionof(s_value, *inits_s) - attrfamily.attrs['__init__'] = s_value + s_value = annmodel.unionof(attrfamily.s_value, *inits_s) + attrfamily.s_value = s_value # ClassesPBCRepr.call() will also need instantiate() support for desc in descs: bk.needs_generic_instantiate[desc.getuniqueclassdef()] = True Modified: pypy/dist/pypy/rpython/ootypesystem/rclass.py ============================================================================== --- pypy/dist/pypy/rpython/ootypesystem/rclass.py (original) +++ pypy/dist/pypy/rpython/ootypesystem/rclass.py Fri May 5 19:29:42 2006 @@ -53,12 +53,11 @@ # attributes showing up in getattrs done on the class as a PBC extra_access_sets = self.rtyper.class_pbc_attributes.get( self.classdef, {}) - for access_set, counter in extra_access_sets.items(): - for attr, s_value in access_set.attrs.items(): - r = self.rtyper.getrepr(s_value) - mangled_name = pbcmangle('pbc%d' % counter, attr) - pbcfields[access_set, attr] = mangled_name, r - llfields.append((mangled_name, r.lowleveltype)) + for access_set, (attr, counter) in extra_access_sets.items(): + r = self.rtyper.getrepr(access_set.s_value) + mangled_name = pbcmangle('pbc%d' % counter, attr) + pbcfields[access_set, attr] = mangled_name, r + llfields.append((mangled_name, r.lowleveltype)) self.rbase.setup() ootype.addFields(self.lowleveltype, dict(llfields)) Modified: pypy/dist/pypy/rpython/rpbc.py ============================================================================== --- pypy/dist/pypy/rpython/rpbc.py (original) +++ pypy/dist/pypy/rpython/rpbc.py Fri May 5 19:29:42 2006 @@ -599,24 +599,22 @@ self.lowleveltype = Void else: self.lowleveltype = rtyper.type_system.rclass.CLASSTYPE - self._access_set = None - self._class_repr = None - def get_access_set(self): - if self._access_set is None: - classdescs = self.s_pbc.descriptions.keys() - access = classdescs[0].getattrfamily() - for classdesc in classdescs[1:]: - access1 = classdesc.getattrfamily() - assert access1 is access # XXX not implemented - commonbase = access.commonbase - self._class_repr = rclass.getclassrepr(self.rtyper, commonbase) - self._access_set = access - return self._access_set - - def get_class_repr(self): - self.get_access_set() - return self._class_repr + def get_access_set(self, attrname): + """Return the ClassAttrFamily corresponding to accesses to 'attrname' + and the ClassRepr of the class which stores this attribute in + its vtable. + """ + classdescs = self.s_pbc.descriptions.keys() + access = classdescs[0].queryattrfamily(attrname) + for classdesc in classdescs[1:]: + access1 = classdesc.queryattrfamily(attrname) + assert access1 is access # XXX not implemented + if access is None: + raise rclass.MissingRTypeAttribute(attrname) + commonbase = access.commonbase + class_repr = rclass.getclassrepr(self.rtyper, commonbase) + return access, class_repr def convert_desc(self, desc): if desc not in self.s_pbc.descriptions: @@ -635,11 +633,10 @@ return hop.inputconst(hop.r_result, hop.s_result.const) else: attr = hop.args_s[1].const - access_set = self.get_access_set() - class_repr = self.get_class_repr() + access_set, class_repr = self.get_access_set(attr) vcls, vattr = hop.inputargs(class_repr, Void) v_res = class_repr.getpbcfield(vcls, access_set, attr, hop.llops) - s_res = access_set.attrs[attr] + s_res = access_set.s_value r_res = self.rtyper.getrepr(s_res) return hop.llops.convertvar(v_res, r_res, hop.r_result) @@ -663,11 +660,8 @@ if r_clspbc.lowleveltype is Void: return inputconst(r_cls, r_clspbc.s_pbc.const) # convert from ptr-to-object-vtable to ptr-to-more-precise-vtable - # but first check if it is safe assert (r_clspbc.lowleveltype == r_clspbc.rtyper.type_system.rclass.CLASSTYPE) - if not r_clspbc.get_class_repr().classdef.issubclass(r_cls.classdef): - return NotImplemented return r_cls.fromclasstype(v, llops) class __extend__(pairtype(AbstractClassesPBCRepr, AbstractClassesPBCRepr)): 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 May 5 19:29:42 2006 @@ -1220,6 +1220,33 @@ res = interpret(f, [1], type_system=self.ts) assert res == 65 + def test_multiple_attribute_access_patterns(self): + class Base(object): + pass + class A(Base): + value = 1000 + def meth(self): return self.n + 1 + class B(A): + def meth(self): return self.n + 2 + class C(Base): + value = 2000 + def meth(self): ShouldNotBeSeen + def AorB(n): + if n == 5: return A + else: return B + def BorC(n): + if n == 3: return B + else: return C + def f(n): + value = BorC(n).value + x = B() + x.n = 100 + return value + AorB(n).meth(x) + + for i in [1, 3, 5]: + res = interpret(f, [i]) + assert res == f(i) + def test_call_from_list(): # Don't test with ootype, since it doesn't support lists in a From arigo at codespeak.net Fri May 5 19:34:09 2006 From: arigo at codespeak.net (arigo at codespeak.net) Date: Fri, 5 May 2006 19:34:09 +0200 (CEST) Subject: [pypy-svn] r26823 - pypy/dist/pypy/objspace/std Message-ID: <20060505173409.6988B10094@code0.codespeak.net> Author: arigo Date: Fri May 5 19:34:08 2006 New Revision: 26823 Modified: pypy/dist/pypy/objspace/std/objspace.py Log: This should have been part of the __weakref__ check-in. Modified: pypy/dist/pypy/objspace/std/objspace.py ============================================================================== --- pypy/dist/pypy/objspace/std/objspace.py (original) +++ pypy/dist/pypy/objspace/std/objspace.py Fri May 5 19:34:08 2006 @@ -189,7 +189,7 @@ from _file import file as libfile for name, value in libfile.__dict__.items(): if (name != '__dict__' and name != '__doc__' - and name != '__module__'): + and name != '__module__' and name != '__weakref__'): setattr(file, name, value) sys.stdin._fdopen(0, "r", 1, '') sys.stdout._fdopen(1, "w", 1, '') From arigo at codespeak.net Fri May 5 20:26:21 2006 From: arigo at codespeak.net (arigo at codespeak.net) Date: Fri, 5 May 2006 20:26:21 +0200 (CEST) Subject: [pypy-svn] r26825 - in pypy/dist/pypy: interpreter interpreter/test objspace objspace/std objspace/std/test Message-ID: <20060505182621.79C3210092@code0.codespeak.net> Author: arigo Date: Fri May 5 20:26:12 2006 New Revision: 26825 Modified: pypy/dist/pypy/interpreter/baseobjspace.py pypy/dist/pypy/interpreter/function.py pypy/dist/pypy/interpreter/pycode.py pypy/dist/pypy/interpreter/test/test_code.py pypy/dist/pypy/interpreter/test/test_function.py pypy/dist/pypy/interpreter/typedef.py pypy/dist/pypy/objspace/descroperation.py pypy/dist/pypy/objspace/std/complextype.py pypy/dist/pypy/objspace/std/dictobject.py pypy/dist/pypy/objspace/std/dicttype.py pypy/dist/pypy/objspace/std/floattype.py pypy/dist/pypy/objspace/std/frozensettype.py pypy/dist/pypy/objspace/std/inttype.py pypy/dist/pypy/objspace/std/listobject.py pypy/dist/pypy/objspace/std/listtype.py pypy/dist/pypy/objspace/std/longtype.py pypy/dist/pypy/objspace/std/objecttype.py pypy/dist/pypy/objspace/std/setobject.py pypy/dist/pypy/objspace/std/settype.py pypy/dist/pypy/objspace/std/sliceobject.py pypy/dist/pypy/objspace/std/slicetype.py pypy/dist/pypy/objspace/std/stdtypedef.py pypy/dist/pypy/objspace/std/stringtype.py pypy/dist/pypy/objspace/std/test/test_obj.py pypy/dist/pypy/objspace/std/tupletype.py pypy/dist/pypy/objspace/std/unicodetype.py Log: Hash support: some Wrappables were missing a hash. The main work in this check-in, though, is about making sure the hash_cache field inserted by the rtyper for instances on which hash() is called, only shows up in selected subclasses of W_Root instead of on W_Root. Classes like W_IntObject and W_TupleObject don't need it. (This is a step towards tagged pointers, which has no chance to work if the W_SmallIntObject class contains more than an 'intval' field.) Modified: pypy/dist/pypy/interpreter/baseobjspace.py ============================================================================== --- pypy/dist/pypy/interpreter/baseobjspace.py (original) +++ pypy/dist/pypy/interpreter/baseobjspace.py Fri May 5 20:26:12 2006 @@ -4,7 +4,7 @@ from pypy.interpreter.pycompiler import CPythonCompiler, PythonAstCompiler from pypy.interpreter.miscutils import ThreadLocals from pypy.tool.cache import Cache -from pypy.rpython.rarithmetic import r_uint, intmask +from pypy.rpython.rarithmetic import r_uint import os __all__ = ['ObjSpace', 'OperationError', 'Wrappable', 'W_Root'] @@ -58,9 +58,6 @@ def setslotvalue(self, index, w_val): raise NotImplementedError - def identity_hash(self, space): - return space.wrap(intmask(hash(self))) #space.id(self) - # used by _weakref implemenation def getweakref(self): Modified: pypy/dist/pypy/interpreter/function.py ============================================================================== --- pypy/dist/pypy/interpreter/function.py (original) +++ pypy/dist/pypy/interpreter/function.py Fri May 5 20:26:12 2006 @@ -385,10 +385,23 @@ other = space.interpclass_w(w_other) if not isinstance(other, Method): return space.w_False - if not space.is_w(self.w_instance, other.w_instance): - return space.w_False + if self.w_instance is None: + if other.w_instance is not None: + return space.w_False + else: + if other.w_instance is None: + return space.w_False + if not space.is_w(self.w_instance, other.w_instance): + return space.w_False return space.eq(self.w_function, other.w_function) + def descr_method_hash(self): + space = self.space + w_result = space.hash(self.w_function) + if self.w_instance is not None: + w_result = space.xor(w_result, space.hash(self.w_instance)) + return w_result + def descr_method__reduce__(self, space): from pypy.interpreter.mixedmodule import MixedModule w_mod = space.getbuiltinmodule('_pickle_support') Modified: pypy/dist/pypy/interpreter/pycode.py ============================================================================== --- pypy/dist/pypy/interpreter/pycode.py (original) +++ pypy/dist/pypy/interpreter/pycode.py Fri May 5 20:26:12 2006 @@ -11,6 +11,7 @@ from pypy.interpreter.gateway import NoneNotWrapped from pypy.interpreter.baseobjspace import ObjSpace, W_Root from pypy.interpreter.mixedmodule import MixedModule +from pypy.rpython.rarithmetic import intmask # helper @@ -343,7 +344,25 @@ return space.w_False return space.w_True - + + def descr_code__hash__(self): + space = self.space + result = hash(self.co_name) + result ^= self.co_argcount + result ^= self.co_nlocals + result ^= self.co_flags + result ^= self.co_firstlineno + result ^= hash(self.co_code) + for name in self.co_varnames: result ^= hash(name) + for name in self.co_freevars: result ^= hash(name) + for name in self.co_cellvars: result ^= hash(name) + w_result = space.wrap(intmask(result)) + for w_name in self.co_names_w: + w_result = space.xor(w_result, space.hash(w_name)) + for w_const in self.co_consts_w: + w_result = space.xor(w_result, space.hash(w_const)) + return w_result + unwrap_spec = [ObjSpace, W_Root, int, int, int, int, str, W_Root, W_Root, @@ -403,4 +422,4 @@ space.newtuple([w(v) for v in self.co_cellvars]), #hidden_applevel=False, magic = 62061 | 0x0a0d0000 ] - return space.newtuple([new_inst, space.newtuple(tup)]) \ No newline at end of file + return space.newtuple([new_inst, space.newtuple(tup)]) Modified: pypy/dist/pypy/interpreter/test/test_code.py ============================================================================== --- pypy/dist/pypy/interpreter/test/test_code.py (original) +++ pypy/dist/pypy/interpreter/test/test_code.py Fri May 5 20:26:12 2006 @@ -120,3 +120,11 @@ ccode.co_name, ccode.co_firstlineno, ccode.co_lnotab) + + def test_hash(self): + d1 = {} + exec "def f(): pass" in d1 + d2 = {} + exec "def f(): pass" in d2 + assert d1['f'].func_code == d2['f'].func_code + assert hash(d1['f'].func_code) == hash(d2['f'].func_code) Modified: pypy/dist/pypy/interpreter/test/test_function.py ============================================================================== --- pypy/dist/pypy/interpreter/test/test_function.py (original) +++ pypy/dist/pypy/interpreter/test/test_function.py Fri May 5 20:26:12 2006 @@ -206,6 +206,15 @@ assert (c.m != c2.m) is True assert (c.m != c.m) is False + def test_method_hash(self): + class C(object): + def m(): pass + class D(C): + pass + c = C() + assert hash(C.m) == hash(D.m) + assert hash(c.m) == hash(c.m) + def test_method_repr(self): class A(object): def f(self): Modified: pypy/dist/pypy/interpreter/typedef.py ============================================================================== --- pypy/dist/pypy/interpreter/typedef.py (original) +++ pypy/dist/pypy/interpreter/typedef.py Fri May 5 20:26:12 2006 @@ -7,8 +7,9 @@ from pypy.interpreter.argument import Arguments from pypy.interpreter.baseobjspace import Wrappable, W_Root, ObjSpace from pypy.interpreter.error import OperationError -from pypy.tool.sourcetools import compile2 +from pypy.tool.sourcetools import compile2, func_with_new_name from pypy.rpython.objectmodel import instantiate +from pypy.rpython.rarithmetic import intmask class TypeDef: def __init__(self, __name, __base=None, **rawdict): @@ -17,9 +18,12 @@ self.base = __base self.hasdict = '__dict__' in rawdict self.weakrefable = '__weakref__' in rawdict + self.custom_hash = '__hash__' in rawdict if __base is not None: - self.hasdict |= __base.hasdict + self.hasdict |= __base.hasdict self.weakrefable |= __base.weakrefable + self.custom_hash |= __base.custom_hash + # NB. custom_hash is sometimes overridden manually by callers self.rawdict = {} self.acceptable_as_base_class = True # xxx used by faking @@ -38,6 +42,53 @@ return True +# ____________________________________________________________ +# Hash support + +def get_default_hash_function(cls): + # go to the first parent class of 'cls' that as a typedef + while 'typedef' not in cls.__dict__: + print cls, '=> !' + cls = cls.__bases__[0] + if cls is object: + # not found: 'cls' must have been an abstract class, + # no hash function is needed + return None + if cls.typedef.custom_hash: + return None # the typedef says that instances have their own + # hash, so we don't need a default RPython-level + # hash function. + try: + hashfunction = _hashfunction_cache[cls] + except KeyError: + def hashfunction(w_obj): + "Return the identity hash of 'w_obj'." + assert isinstance(w_obj, cls) + return hash(w_obj) # forces a hash_cache only on 'cls' instances + hashfunction = func_with_new_name(hashfunction, + 'hashfunction_for_%s' % (cls.__name__,)) + _hashfunction_cache[cls] = hashfunction + return hashfunction +get_default_hash_function._annspecialcase_ = 'specialize:memo' +_hashfunction_cache = {} + +def default_identity_hash(space, w_obj): + fn = get_default_hash_function(w_obj.__class__) + if fn is None: + typename = space.type(w_obj).getname(space, '?') + msg = "%s objects have no default hash" % (typename,) + raise OperationError(space.w_TypeError, space.wrap(msg)) + return space.wrap(intmask(fn(w_obj))) + +def descr__hash__unhashable(space, w_obj): + typename = space.type(w_obj).getname(space, '?') + msg = "%s objects are unhashable" % (typename,) + raise OperationError(space.w_TypeError,space.wrap(msg)) + +no_hash_descr = interp2app(descr__hash__unhashable) + +# ____________________________________________________________ + def get_unique_interplevel_subclass(cls, hasdict, wants_slots, needsdel=False, weakrefable=False): key = cls, hasdict, wants_slots, needsdel, weakrefable @@ -451,6 +502,7 @@ __new__ = interp2app(PyCode.descr_code__new__.im_func), __eq__ = interp2app(PyCode.descr_code__eq__), __ne__ = descr_generic_ne, + __hash__ = interp2app(PyCode.descr_code__hash__), __reduce__ = interp2app(PyCode.descr__reduce__, unwrap_spec=['self', ObjSpace]), co_argcount = interp_attrproperty('co_argcount', cls=PyCode), @@ -535,7 +587,6 @@ __dict__ = getset_func_dict, __module__ = getset___module__, __weakref__ = make_weakref_descr(Function), - # XXX func_closure, etc.pp ) Method.typedef = TypeDef("method", @@ -549,16 +600,15 @@ __getattribute__ = interp2app(Method.descr_method_getattribute), __eq__ = interp2app(Method.descr_method_eq), __ne__ = descr_generic_ne, + __hash__ = interp2app(Method.descr_method_hash), __repr__ = interp2app(Method.descr_method_repr), __reduce__ = interp2app(Method.descr_method__reduce__, unwrap_spec=['self', ObjSpace]), __weakref__ = make_weakref_descr(Method), - # XXX getattribute/setattribute etc.pp ) StaticMethod.typedef = TypeDef("staticmethod", __get__ = interp2app(StaticMethod.descr_staticmethod_get), - # XXX getattribute etc.pp ) def always_none(self, obj): @@ -590,6 +640,7 @@ __eq__ = interp2app(Cell.descr__eq__, unwrap_spec=['self', ObjSpace, W_Root]), __ne__ = descr_generic_ne, + __hash__ = no_hash_descr, __reduce__ = interp2app(Cell.descr__reduce__, unwrap_spec=['self', ObjSpace]), __setstate__ = interp2app(Cell.descr__setstate__, Modified: pypy/dist/pypy/objspace/descroperation.py ============================================================================== --- pypy/dist/pypy/objspace/descroperation.py (original) +++ pypy/dist/pypy/objspace/descroperation.py Fri May 5 20:26:12 2006 @@ -3,6 +3,7 @@ from pypy.interpreter.baseobjspace import ObjSpace from pypy.interpreter.function import Function, Method from pypy.interpreter.argument import Arguments +from pypy.interpreter.typedef import default_identity_hash from pypy.tool.sourcetools import compile2, func_with_new_name def raiseattrerror(space, w_obj, name, w_descr=None): @@ -285,7 +286,7 @@ space.lookup(w_obj, '__cmp__') is not None: raise OperationError(space.w_TypeError, space.wrap("unhashable type")) - return w_obj.identity_hash(space) + return default_identity_hash(space, w_obj) w_result = space.get_and_call_function(w_hash, w_obj) if space.is_true(space.isinstance(w_result, space.w_int)): return w_result Modified: pypy/dist/pypy/objspace/std/complextype.py ============================================================================== --- pypy/dist/pypy/objspace/std/complextype.py (original) +++ pypy/dist/pypy/objspace/std/complextype.py Fri May 5 20:26:12 2006 @@ -204,4 +204,5 @@ imag = complexwprop('imagval'), ) +complex_typedef.custom_hash = True complex_typedef.registermethods(globals()) Modified: pypy/dist/pypy/objspace/std/dictobject.py ============================================================================== --- pypy/dist/pypy/objspace/std/dictobject.py (original) +++ pypy/dist/pypy/objspace/std/dictobject.py Fri May 5 20:26:12 2006 @@ -147,9 +147,6 @@ w_res = space.lt(w_leftval, w_rightval) return w_res -def hash__Dict(space,w_dict): - raise OperationError(space.w_TypeError,space.wrap("dict objects are unhashable")) - def dict_copy__Dict(space, w_self): return W_DictObject(space, w_self) Modified: pypy/dist/pypy/objspace/std/dicttype.py ============================================================================== --- pypy/dist/pypy/objspace/std/dicttype.py (original) +++ pypy/dist/pypy/objspace/std/dicttype.py Fri May 5 20:26:12 2006 @@ -118,6 +118,7 @@ in the keyword argument list. For example: dict(one=1, two=2)''', __new__ = newmethod(descr__new__, unwrap_spec=[gateway.ObjSpace,gateway.W_Root,gateway.Arguments]), + __hash__ = no_hash_descr, ) dict_typedef.registermethods(globals()) Modified: pypy/dist/pypy/objspace/std/floattype.py ============================================================================== --- pypy/dist/pypy/objspace/std/floattype.py (original) +++ pypy/dist/pypy/objspace/std/floattype.py Fri May 5 20:26:12 2006 @@ -47,3 +47,4 @@ Convert a string or number to a floating point number, if possible.''', __new__ = newmethod(descr__new__), ) +float_typedef.custom_hash = True Modified: pypy/dist/pypy/objspace/std/frozensettype.py ============================================================================== --- pypy/dist/pypy/objspace/std/frozensettype.py (original) +++ pypy/dist/pypy/objspace/std/frozensettype.py Fri May 5 20:26:12 2006 @@ -34,4 +34,5 @@ __new__ = newmethod(descr__frozenset__new__), ) +frozenset_typedef.custom_hash = True frozenset_typedef.registermethods(globals()) Modified: pypy/dist/pypy/objspace/std/inttype.py ============================================================================== --- pypy/dist/pypy/objspace/std/inttype.py (original) +++ pypy/dist/pypy/objspace/std/inttype.py Fri May 5 20:26:12 2006 @@ -99,3 +99,4 @@ will be returned instead.''', __new__ = newmethod(descr__new__), ) +int_typedef.custom_hash = True Modified: pypy/dist/pypy/objspace/std/listobject.py ============================================================================== --- pypy/dist/pypy/objspace/std/listobject.py (original) +++ pypy/dist/pypy/objspace/std/listobject.py Fri May 5 20:26:12 2006 @@ -299,9 +299,6 @@ w_currently_in_repr = space.getexecutioncontext()._py_repr return listrepr(space, w_currently_in_repr, w_list) -def hash__List(space,w_list): - raise OperationError(space.w_TypeError,space.wrap("list objects are unhashable")) - def list_insert__List_ANY_ANY(space, w_list, w_where, w_any): where = space.int_w(w_where) length = len(w_list.wrappeditems) Modified: pypy/dist/pypy/objspace/std/listtype.py ============================================================================== --- pypy/dist/pypy/objspace/std/listtype.py (original) +++ pypy/dist/pypy/objspace/std/listtype.py Fri May 5 20:26:12 2006 @@ -46,5 +46,6 @@ __new__ = newmethod(descr__new__, unwrap_spec=[gateway.ObjSpace, gateway.W_Root, gateway.Arguments]), + __hash__ = no_hash_descr, ) list_typedef.registermethods(globals()) Modified: pypy/dist/pypy/objspace/std/longtype.py ============================================================================== --- pypy/dist/pypy/objspace/std/longtype.py (original) +++ pypy/dist/pypy/objspace/std/longtype.py Fri May 5 20:26:12 2006 @@ -81,3 +81,4 @@ converting a non-string.''', __new__ = newmethod(descr__new__), ) +long_typedef.custom_hash = True Modified: pypy/dist/pypy/objspace/std/objecttype.py ============================================================================== --- pypy/dist/pypy/objspace/std/objecttype.py (original) +++ pypy/dist/pypy/objspace/std/objecttype.py Fri May 5 20:26:12 2006 @@ -1,6 +1,7 @@ from pypy.interpreter.error import OperationError from pypy.objspace.descroperation import Object from pypy.interpreter import gateway +from pypy.interpreter.typedef import default_identity_hash from pypy.objspace.std.stdtypedef import * from pypy.objspace.std.register_all import register_all from pypy.objspace.std.objspace import StdObjSpace @@ -53,9 +54,6 @@ W_ObjectObject.__init__(w_obj, space) return w_obj -def descr__hash__(space, w_obj): - return w_obj.identity_hash(space) - def descr__init__(space, w_obj, __args__): pass @@ -162,7 +160,7 @@ __doc__ = '''The most base type''', __new__ = newmethod(descr__new__, unwrap_spec = [gateway.ObjSpace,gateway.W_Root,gateway.Arguments]), - __hash__ = gateway.interp2app(descr__hash__), + __hash__ = gateway.interp2app(default_identity_hash), __reduce_ex__ = gateway.interp2app(descr__reduce_ex__, unwrap_spec=[gateway.ObjSpace,gateway.W_Root,int]), __reduce__ = gateway.interp2app(descr__reduce_ex__, @@ -170,3 +168,5 @@ __init__ = gateway.interp2app(descr__init__, unwrap_spec=[gateway.ObjSpace,gateway.W_Root,gateway.Arguments]), ) + +object_typedef.custom_hash = False # object.__hash__ is not a custom hash Modified: pypy/dist/pypy/objspace/std/setobject.py ============================================================================== --- pypy/dist/pypy/objspace/std/setobject.py (original) +++ pypy/dist/pypy/objspace/std/setobject.py Fri May 5 20:26:12 2006 @@ -388,10 +388,6 @@ raise OperationError(space.w_KeyError, space.call_method(w_item,'__repr__')) -def hash__Set(space, w_set): - raise OperationError(space.w_TypeError, - space.wrap('set objects are unhashable')) - def hash__Frozenset(space, w_set): multi = r_uint(1822399083) + r_uint(1822399083) + 1 if w_set.hash != -1: Modified: pypy/dist/pypy/objspace/std/settype.py ============================================================================== --- pypy/dist/pypy/objspace/std/settype.py (original) +++ pypy/dist/pypy/objspace/std/settype.py Fri May 5 20:26:12 2006 @@ -39,6 +39,7 @@ __new__ = newmethod(descr__new__, unwrap_spec=[gateway.ObjSpace, gateway.W_Root, gateway.Arguments]), + __hash__ = no_hash_descr, ) set_typedef.registermethods(globals()) Modified: pypy/dist/pypy/objspace/std/sliceobject.py ============================================================================== --- pypy/dist/pypy/objspace/std/sliceobject.py (original) +++ pypy/dist/pypy/objspace/std/sliceobject.py Fri May 5 20:26:12 2006 @@ -111,10 +111,6 @@ else: return space.lt(w_slice1.w_start, w_slice2.w_start) -def hash__Slice(space, w_slice): - """slices are not hashables but they must have a __hash__ method""" - raise OperationError(space.w_TypeError, - space.wrap("unhashable type")) # indices impl def slice_indices__Slice_ANY(space, w_slice, w_length): Modified: pypy/dist/pypy/objspace/std/slicetype.py ============================================================================== --- pypy/dist/pypy/objspace/std/slicetype.py (original) +++ pypy/dist/pypy/objspace/std/slicetype.py Fri May 5 20:26:12 2006 @@ -79,6 +79,7 @@ Create a slice object. This is used for extended slicing (e.g. a[0:10:2]).''', __new__ = newmethod(descr__new__), + __hash__ = no_hash_descr, start = slicewprop('w_start'), stop = slicewprop('w_stop'), step = slicewprop('w_step'), Modified: pypy/dist/pypy/objspace/std/stdtypedef.py ============================================================================== --- pypy/dist/pypy/objspace/std/stdtypedef.py (original) +++ pypy/dist/pypy/objspace/std/stdtypedef.py Fri May 5 20:26:12 2006 @@ -2,6 +2,7 @@ from pypy.interpreter.error import OperationError from pypy.interpreter.typedef import TypeDef, GetSetProperty, Member from pypy.interpreter.typedef import descr_get_dict, descr_set_dict +from pypy.interpreter.typedef import no_hash_descr from pypy.interpreter.baseobjspace import SpaceCache from pypy.objspace.std.model import StdObjSpaceMultiMethod from pypy.objspace.std.multimethod import FailedToImplement @@ -9,7 +10,7 @@ __all__ = ['StdTypeDef', 'newmethod', 'gateway', 'GetSetProperty', 'Member', - 'StdObjSpaceMultiMethod', 'descr_get_dict'] + 'StdObjSpaceMultiMethod', 'descr_get_dict', 'no_hash_descr'] class StdTypeDef(TypeDef): Modified: pypy/dist/pypy/objspace/std/stringtype.py ============================================================================== --- pypy/dist/pypy/objspace/std/stringtype.py (original) +++ pypy/dist/pypy/objspace/std/stringtype.py Fri May 5 20:26:12 2006 @@ -60,4 +60,6 @@ Return a nice string representation of the object. If the argument is a string, the return value is the same object.''' ) + +str_typedef.custom_hash = True str_typedef.registermethods(globals()) Modified: pypy/dist/pypy/objspace/std/test/test_obj.py ============================================================================== --- pypy/dist/pypy/objspace/std/test/test_obj.py (original) +++ pypy/dist/pypy/objspace/std/test/test_obj.py Fri May 5 20:26:12 2006 @@ -16,3 +16,10 @@ def test_no_getnewargs(self): o = object() assert not hasattr(o, '__getnewargs__') + + def test_hash_subclass(self): + class X(object): + pass + x = X() + assert hash(x) == id(x) + assert hash(x) == object.__hash__(x) Modified: pypy/dist/pypy/objspace/std/tupletype.py ============================================================================== --- pypy/dist/pypy/objspace/std/tupletype.py (original) +++ pypy/dist/pypy/objspace/std/tupletype.py Fri May 5 20:26:12 2006 @@ -23,3 +23,4 @@ If the argument is a tuple, the return value is the same object.''', __new__ = newmethod(descr__new__), ) +tuple_typedef.custom_hash = True Modified: pypy/dist/pypy/objspace/std/unicodetype.py ============================================================================== --- pypy/dist/pypy/objspace/std/unicodetype.py (original) +++ pypy/dist/pypy/objspace/std/unicodetype.py Fri May 5 20:26:12 2006 @@ -136,4 +136,6 @@ encoding defaults to the current default string encoding. errors can be 'strict', 'replace' or 'ignore' and defaults to 'strict'.''' ) + +unicode_typedef.custom_hash = True unicode_typedef.registermethods(globals()) From cfbolz at codespeak.net Fri May 5 20:39:33 2006 From: cfbolz at codespeak.net (cfbolz at codespeak.net) Date: Fri, 5 May 2006 20:39:33 +0200 (CEST) Subject: [pypy-svn] r26827 - pypy/extradoc/talk/agile2006 Message-ID: <20060505183933.99E2B1008F@code0.codespeak.net> Author: cfbolz Date: Fri May 5 20:39:25 2006 New Revision: 26827 Added: pypy/extradoc/talk/agile2006/paper.sty Modified: pypy/extradoc/talk/agile2006/draftpaper_agile2006.pdf pypy/extradoc/talk/agile2006/draftpaper_agile2006.txt Log: restify and use some raw latex to make result look nicer. Modified: pypy/extradoc/talk/agile2006/draftpaper_agile2006.pdf ============================================================================== Binary files. No diff available. Modified: pypy/extradoc/talk/agile2006/draftpaper_agile2006.txt ============================================================================== --- pypy/extradoc/talk/agile2006/draftpaper_agile2006.txt (original) +++ pypy/extradoc/talk/agile2006/draftpaper_agile2006.txt Fri May 5 20:39:25 2006 @@ -3,9 +3,12 @@ =================================================================================== .. sectnum + +.. role:: raw-latex(raw) + :format: latex + .. raw:: latex - \author{Beatrice During, Change Maker, bea at changemaker.nu} \begin{abstract} PyPy is an Open Source project, partly funded by the European Union, employing @@ -370,10 +373,11 @@ Here is what one of the new core developers of PyPy says about sync-meetings: -"Sync-meetings are useful because they enable developers to discuss and clarify issues -among themselves and to provide a common focus when working distributedly. They -are also a lightweight way to syncronize activities, resolve blockers and to get an -overview about who is currently doing what work." + *"Sync-meetings are useful because they enable developers to discuss and + clarify issues among themselves and to provide a common focus when working + distributedly. They are also a lightweight way to syncronize activities, + resolve blockers and to get an overview about who is currently doing what + work."* Influencing factors: agile practices in PyPy ============================================ @@ -506,15 +510,16 @@ management team the strategy implemented was to delegate as much as possible of the responsibilities and decision-making to the core developers. -The strategy was to keep "conceptual integrity" [1] of the vision and the -idea in the hands of the core developers. As Brooks stresses, a uniform system -design is better than uncoordinated and independent design ideas. The core developers -had a clear and agreed vision - but would they be allowed to implement it within a -fixed contract workstyle, with new partners involved that had not been involved in -the process from the start? The core developers were organized into a technical -board, responsible for planning and coordinating the development work between -the partners, with the mandate to make decisions. A somewhat negative result -was the added workload and responsibility on developers regarding EU related work. +The strategy was to keep "conceptual integrity" :raw-latex:`\cite{key-1}` of +the vision and the idea in the hands of the core developers. As Brooks +stresses, a uniform system design is better than uncoordinated and independent +design ideas. The core developers had a clear and agreed vision - but would +they be allowed to implement it within a fixed contract workstyle, with new +partners involved that had not been involved in the process from the start? The +core developers were organized into a technical board, responsible for planning +and coordinating the development work between the partners, with the mandate to +make decisions. A somewhat negative result was the added workload and +responsibility on developers regarding EU related work. This structure was the most difficult to design and implement due to the very different nature of its purpose compared to the collaborative, self-organized @@ -559,8 +564,8 @@ development method as well as filming talks and discussion. Our film material is planned to be released before summer 2006. -Troubles in Paradise:striking a balance -======================================= +Troubles in Paradise: striking a balance +======================================== Developer driven versus formal project structure ------------------------------------------------ @@ -653,95 +658,114 @@ We believe so. The one clear dominating factor to make all this succeed is, as always, the people factor, the CRACK performers as Boehm and Turner calls them -("Collaborative, Representative, Authorized, Committed, Knowledgeable"). [2] +("Collaborative, Representative, Authorized, Committed, Knowledgeable") +:raw-latex:`\cite{key-2}`. The core developers of the PyPy project had the right mix of various skills in order to succeed in setting up a hybrid environment - enabling them to work full time on a project they strongly believed in. The most crucial mix of skills for making this possible was/are: -- Social -The ability to communicate open and transparent, to mentor and tutor dispersed -as well as reinventing different collaborative workstyles of the sprint method, -"manage" groups and community as well as consortium, and handle conflicts) - -- Leadership abilities -The ability to step into formal leadership roles in technical board structures, manage -sprints and sync-meetings as well as the more informal management of the community -of developers. Managing the balance between encouraging participation but still holding -true to their vision, their "conceptual integrity". - -- Ability to network -To be open to other communities, inviting new partners in order to create a working -consortium structure in the EU-project, curious and collaborative towards other Python -implementations and other languages and research approaches, sharing knowledge and -experiences and seeking bets practices of other projects. - -- Entrepreneurs -To risk the community through pursuing the idea of EU-funding in order to fullfill the -ambitious vision, managing to not only create a consortium with innovative -structures of cooperation but also to create new companies. - -- Technical skills -Programming language and implementation aspects,frameworks, mathematics, computer -science - core skills for the project. Also the ability to design, setup and effectively manage -supporting infrastructure for the development process. - -- Managing the balance between encouraging participation but still holding -true to their vision, their "conceptual integrity" -This while working agile with open and transparent communication through sprints, -documentation, tutorials, mentoring, sync-meetings. Resulting in a lively and growing -the F/OSS community around the project. - -So, could it be said that for an agile software development process, especially one that is -distributed and community oriented, within a framework of EU-funding, that it is heavily -people dependent? Or to stress it even further, sprint-driven development as a methodology -does not exist and function without an agile group of people, Crack performers. The people -are the methodology in some sense and if you wish to draw upon the experience of the PyPy -team you need to look at the supporting practices around the people in order to find what can be -duplicated and tested in another project environment. This conclusion matches what Alistair -Cockburn writes in his paper "Characterizing People as Non-Linear, First-Order Components in -Software Development" [3]: - -"The fundamental characteristics of "people" have a first-order -effect on software development, not a lower-order effect." - -If we accept this conclusion then we can also, thanks to the people, start to get innovative -regarding practices. Designing the project process based on the specific needs of the unique -project environment you are facing. In the case of PyPy this means that we are exploring -the methodology as we go along, adjusting and finetuning the process as well as the software. - -So, when drawing from these different skills within the community of developers, the people, in -the PyPy project one possible conclusion would be that a truly agile approach -dominating the work style of an Open Source project will increase the ability of -the community to spread the strategy of agility to other domains. - -By this we mean that what started as agile practices in the development process -quickly became influencing factors when designing other project processes. Examples of -this in PyPy is how the sprint-driven development acts as a focal point not just for the -development work (co-located as well as dispersed) but also for the formal and informal -management of the project. Sprints together with the CRACK performers was what made -the community grow and evolve. It was the foundation for a hybrid project where agile -practices and EU-funding can fit within a distributed Open Source context. +- **Social:** The ability to communicate open and transparent, to mentor and + tutor dispersed as well as reinventing different collaborative workstyles of + the sprint method, "manage" groups and community as well as consortium, and + handle conflicts) + +- **Leadership abilities:** The ability to step into formal leadership roles in + technical board structures, manage sprints and sync-meetings as well as the + more informal management of the community of developers. Managing the balance + between encouraging participation but still holding true to their vision, + their "conceptual integrity". + +- **Ability to network:** To be open to other communities, inviting new + partners in order to create a working consortium structure in the EU-project, + curious and collaborative towards other Python implementations and other + languages and research approaches, sharing knowledge and experiences and + seeking bets practices of other projects. + +- **Entrepreneurs:** To risk the community through pursuing the idea of + EU-funding in order to fullfill the ambitious vision, managing to not only + create a consortium with innovative structures of cooperation but also to + create new companies. + +- **Technical skills:** Programming language and implementation + aspects,frameworks, mathematics, computer science - core skills for the + project. Also the ability to design, setup and effectively manage supporting + infrastructure for the development process. + +- Managing the balance between encouraging participation but still holding true + to their vision, their "**conceptual integrity**" This while working agile with + open and transparent communication through sprints, documentation, tutorials, + mentoring, sync-meetings. Resulting in a lively and growing the F/OSS + community around the project. + +So, could it be said that for an agile software development process, especially +one that is distributed and community oriented, within a framework of +EU-funding, that it is heavily people dependent? Or to stress it even further, +sprint-driven development as a methodology does not exist and function without +an agile group of people, Crack performers. The people are the methodology in +some sense and if you wish to draw upon the experience of the PyPy team you +need to look at the supporting practices around the people in order to find +what can be duplicated and tested in another project environment. This +conclusion matches what Alistair Cockburn writes in his paper "Characterizing +People as Non-Linear, First-Order Components in Software Development" +:raw-latex:`\cite{key-3}`: + + *"The fundamental characteristics of "people" have a first-order + effect on software development, not a lower-order effect."* + +If we accept this conclusion then we can also, thanks to the people, start to +get innovative regarding practices. Designing the project process based on the +specific needs of the unique project environment you are facing. In the case of +PyPy this means that we are exploring the methodology as we go along, adjusting +and finetuning the process as well as the software. + +So, when drawing from these different skills within the community of +developers, the people, in the PyPy project one possible conclusion would be +that a truly agile approach dominating the work style of an Open Source project +will increase the ability of the community to spread the strategy of agility to +other domains. + +By this we mean that what started as agile practices in the development process +quickly became influencing factors when designing other project processes. +Examples of this in PyPy is how the sprint-driven development acts as a focal +point not just for the development work (co-located as well as dispersed) but +also for the formal and informal management of the project. Sprints together +with the CRACK performers was what made the community grow and evolve. It was +the foundation for a hybrid project where agile practices and EU-funding can +fit within a distributed Open Source context. + +Acknoledgements +=============== + +The author would like to thank the following people who have in various ways +helped with the creation of this paper: Angela Martin, Emily Bache, Tres +Seaver, Carl Friedrich Bolz. +I would like to dedicate this paper to my dear friend and mentor of the Open +Source Python and PyPy community Holger Krekel. -References: -========== +.. References: +.. =========== + +.. raw:: latex + + \begin{thebibliography}{1} + \bibitem{key-1} Fredrick P. Brooks, Jr, "The mythical man-month, anniversary + edition", Addison-Wesley, 1995 + + \bibitem{key-2} Barry Boehm,Richard Turner, "Observations on Balancing + Discipline and Agility", (drawn from the book "Balancing Agility and + Discipline: A Guide to the Perplexed", Addison Wesley, 2003) + + \bibitem{key-3} Alistair Cockburn, "Characterizing People as Non-Linear, First-Order + Components in Software Development", Presented at the 4th International + Multi-Conference on Systems, Cybernetics and Informatics, Orlando, + Florida, June, 2000, \texttt{http://alistair.cockburn.us/crystal/\\ + articles/cpanfocisd/\\ + characterizingpeopleasnonlinear.html} -[1] Fredrick P. Brooks, Jr, "The mythical man-month, anniversary edition", -Addison-Wesley, 1995 + \end{thebibliography} -[2] Barry Boehm,Richard Turner, "Observations on Balancing Discipline and Agility", -(drawn from the book "Balancing Agility and Discipline: A Guide to the Perplexed", -Addison Wesley, 2003) - -[3] Alistair Cockburn, "Characterizing People as Non-Linear, First-Order Components in -Software Development", Presented at the 4th International Multi-Conference on Systems, -Cybernetics and Informatics, Orlando, Florida, June, 2000, -http://alistair.cockburn.us/crystal/articles/cpanfocisd/characterizingpeopleasnonlinear.html -The author would like to thank the following people who have in various ways helped with the -creation of this paper: Angela Martin, Emily Bache, Tres Seaver, Carl Friedrich Bolz. -I would like to dedicate this paper to my dear friend and mentor of the Open Source Python and -PyPy community Holger Krekel. \ No newline at end of file Added: pypy/extradoc/talk/agile2006/paper.sty ============================================================================== --- (empty file) +++ pypy/extradoc/talk/agile2006/paper.sty Fri May 5 20:39:25 2006 @@ -0,0 +1,2 @@ +\author {Beatrice D\"uring\\ChangeMaker\\\texttt{bea at changemaker.nu}} +\date{} From cfbolz at codespeak.net Fri May 5 20:48:11 2006 From: cfbolz at codespeak.net (cfbolz at codespeak.net) Date: Fri, 5 May 2006 20:48:11 +0200 (CEST) Subject: [pypy-svn] r26828 - pypy/extradoc/talk/agile2006 Message-ID: <20060505184811.681DE1008F@code0.codespeak.net> Author: cfbolz Date: Fri May 5 20:48:03 2006 New Revision: 26828 Modified: pypy/extradoc/talk/agile2006/draftpaper_agile2006.pdf pypy/extradoc/talk/agile2006/draftpaper_agile2006.txt Log: pyot Modified: pypy/extradoc/talk/agile2006/draftpaper_agile2006.pdf ============================================================================== Binary files. No diff available. Modified: pypy/extradoc/talk/agile2006/draftpaper_agile2006.txt ============================================================================== --- pypy/extradoc/talk/agile2006/draftpaper_agile2006.txt (original) +++ pypy/extradoc/talk/agile2006/draftpaper_agile2006.txt Fri May 5 20:48:03 2006 @@ -735,8 +735,8 @@ the foundation for a hybrid project where agile practices and EU-funding can fit within a distributed Open Source context. -Acknoledgements -=============== +Acknowledgements +================ The author would like to thank the following people who have in various ways helped with the creation of this paper: Angela Martin, Emily Bache, Tres From dialtone at codespeak.net Fri May 5 21:23:05 2006 From: dialtone at codespeak.net (dialtone at codespeak.net) Date: Fri, 5 May 2006 21:23:05 +0200 (CEST) Subject: [pypy-svn] r26831 - pypy/dist/pypy/translator/cl/test Message-ID: <20060505192305.B469410094@code0.codespeak.net> Author: dialtone Date: Fri May 5 21:23:04 2006 New Revision: 26831 Modified: pypy/dist/pypy/translator/cl/test/test_list.py Log: more tests that already pass Modified: pypy/dist/pypy/translator/cl/test/test_list.py ============================================================================== --- pypy/dist/pypy/translator/cl/test/test_list.py (original) +++ pypy/dist/pypy/translator/cl/test/test_list.py Fri May 5 21:23:04 2006 @@ -1,5 +1,11 @@ from pypy.translator.cl.buildcl import make_cl_func +def sum_(l): + i = 0 + for item in l: + i = i + item + return i + def test_list_length(): def list_length_one(number): lst = [number] @@ -13,3 +19,37 @@ return lst[0] cl_list_get = make_cl_func(list_get, [int]) assert cl_list_get(1985) == 1985 + +def test_list_iter(): + def list_iter(): + a = 0 + for item in [1,2,3,4,5]: + a = a + item + return a + cl_list_iter = make_cl_func(list_iter) + assert cl_list_iter() == 15 + +def test_list_append(): + def list_append(num): + a = [1,2,3,4] + a.append(num) + return len(a) + cl_list_append = make_cl_func(list_append, [int]) + assert cl_list_append(3) == 5 + +def test_list_concat(): + def list_concat(): + a = [1,2,3,4] + b = [5,6,7,8] + return len(a+b) + cl_list_concat = make_cl_func(list_concat) + assert cl_list_concat() == 8 + +def test_list_setitem(): + def list_setitem(num): + a = [1,2,3,4] + a[1] = num + return sum_(a) + cl_list_setitem = make_cl_func(list_setitem, [int]) + assert cl_list_setitem(10) == 18 + From dialtone at codespeak.net Fri May 5 21:44:57 2006 From: dialtone at codespeak.net (dialtone at codespeak.net) Date: Fri, 5 May 2006 21:44:57 +0200 (CEST) Subject: [pypy-svn] r26833 - in pypy/dist/pypy/translator/cl: . test Message-ID: <20060505194457.C8FCA10094@code0.codespeak.net> Author: dialtone Date: Fri May 5 21:44:56 2006 New Revision: 26833 Modified: pypy/dist/pypy/translator/cl/gencl.py pypy/dist/pypy/translator/cl/opformatter.py pypy/dist/pypy/translator/cl/test/test_dict.py Log: support dict.values() Modified: pypy/dist/pypy/translator/cl/gencl.py ============================================================================== --- pypy/dist/pypy/translator/cl/gencl.py (original) +++ pypy/dist/pypy/translator/cl/gencl.py Fri May 5 21:44:56 2006 @@ -75,15 +75,17 @@ (defun %s (hash) (let ((current-index -1) (keys (loop for keys being the hash-keys in hash collect keys))) - (cons (lambda () - (let ((more (<= (incf current-index) (1- (length keys))))) - (if more - (let* ((key (nth current-index keys)) - (val (gethash key hash))) - (values more key val)) - (values nil nil nil)))) - (lambda () - (nth current-index keys)))))""" % (name) + (list (lambda () + (let ((more (<= (incf current-index) (1- (length keys))))) + (if more + (let* ((key (nth current-index keys)) + (val (gethash key hash))) + (values more key val)) + (values nil nil nil)))) + (lambda () + (nth current-index keys)) + (lambda () + (gethash (nth current-index keys) hash)))))""" % (name) self.declarations[name] = (name, definition) return name Modified: pypy/dist/pypy/translator/cl/opformatter.py ============================================================================== --- pypy/dist/pypy/translator/cl/opformatter.py (original) +++ pypy/dist/pypy/translator/cl/opformatter.py Fri May 5 21:44:56 2006 @@ -214,8 +214,12 @@ def ll_go_next(self): return """\ (multiple-value-bind (more key value) - (funcall (car %s)) + (funcall (first %s)) more)""" % (self.obj,) def ll_current_key(self): - return "(funcall (cdr %s))" % (self.obj,) + return "(funcall (second %s))" % (self.obj,) + + def ll_current_value(self): + return "(funcall (third %s))" % (self.obj,) + Modified: pypy/dist/pypy/translator/cl/test/test_dict.py ============================================================================== --- pypy/dist/pypy/translator/cl/test/test_dict.py (original) +++ pypy/dist/pypy/translator/cl/test/test_dict.py Fri May 5 21:44:56 2006 @@ -22,5 +22,16 @@ for key in dic: i = i + dic[key] return i - cl_dict_iter = make_cl_func(dict_iter, []) + cl_dict_iter = make_cl_func(dict_iter) assert cl_dict_iter() == 12 + +def test_dict_values(): + def dict_values(): + dic = {1:2, 3:4, 5:6} + i = 0 + for value in dic.values(): + i = i + value + return i + cl_dict_value = make_cl_func(dict_values) + assert cl_dict_value() == 12 + From arigo at codespeak.net Fri May 5 22:09:15 2006 From: arigo at codespeak.net (arigo at codespeak.net) Date: Fri, 5 May 2006 22:09:15 +0200 (CEST) Subject: [pypy-svn] r26834 - in pypy/dist/pypy/rpython: . lltypesystem lltypesystem/test Message-ID: <20060505200915.4EB5210097@code0.codespeak.net> Author: arigo Date: Fri May 5 22:09:13 2006 New Revision: 26834 Modified: pypy/dist/pypy/rpython/lltypesystem/rstr.py pypy/dist/pypy/rpython/lltypesystem/rtagged.py pypy/dist/pypy/rpython/lltypesystem/test/test_rtagged.py pypy/dist/pypy/rpython/objectmodel.py Log: Finished rtagged. Modified: pypy/dist/pypy/rpython/lltypesystem/rstr.py ============================================================================== --- pypy/dist/pypy/rpython/lltypesystem/rstr.py (original) +++ pypy/dist/pypy/rpython/lltypesystem/rstr.py Fri May 5 22:09:13 2006 @@ -177,6 +177,9 @@ instance_str_prefix = string_repr.convert_const("<") instance_str_suffix = string_repr.convert_const(" object>") +unboxed_instance_str_prefix = string_repr.convert_const("") + 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/lltypesystem/rtagged.py ============================================================================== --- pypy/dist/pypy/rpython/lltypesystem/rtagged.py (original) +++ pypy/dist/pypy/rpython/lltypesystem/rtagged.py Fri May 5 22:09:13 2006 @@ -43,7 +43,11 @@ return v_instance, False # don't call __init__ def convert_const(self, value): - raise NotImplementedError + if value is None: + return self.null_instance() + else: + number = value.getvalue() + return ll_int_to_unboxed(self.lowleveltype, number) def getfield(self, vinst, attr, llops, force_cast=False): if attr != '__class__': @@ -58,13 +62,22 @@ return cunboxedcls def rtype_type(self, hop): - raise NotImplementedError + [vinst] = hop.inputargs(self) + return self.getfield(vinst, '__class__', hop.llops) def rtype_setattr(self, hop): - raise NotImplementedError + raise TyperError("cannot set attributes on %r" % (self,)) def ll_str(self, i): - raise NotImplementedError + if lltype.cast_ptr_to_int(i) & 1: + from pypy.rpython.lltypesystem import rstr + from pypy.rpython.rint import signed_repr + llstr1 = signed_repr.ll_str(ll_unboxed_to_int(i)) + return rstr.ll_strconcat(rstr.unboxed_instance_str_prefix, + rstr.ll_strconcat(llstr1, + rstr.unboxed_instance_str_suffix)) + else: + return InstanceRepr.ll_str(self, i) def rtype_isinstance(self, hop): if not hop.args_s[1].is_constant(): @@ -84,6 +97,12 @@ minid, maxid, c_answer_if_unboxed) +def ll_int_to_unboxed(PTRTYPE, value): + return lltype.cast_int_to_ptr(PTRTYPE, value*2+1) + +def ll_unboxed_to_int(p): + return lltype.cast_ptr_to_int(p) >> 1 + def ll_unboxed_getclass(instance, class_if_unboxed): if lltype.cast_ptr_to_int(instance) & 1: return class_if_unboxed Modified: pypy/dist/pypy/rpython/lltypesystem/test/test_rtagged.py ============================================================================== --- pypy/dist/pypy/rpython/lltypesystem/test/test_rtagged.py (original) +++ pypy/dist/pypy/rpython/lltypesystem/test/test_rtagged.py Fri May 5 22:09:13 2006 @@ -5,15 +5,24 @@ class A(object): - pass + def meth(self, x): + raise NotImplementedError + class B(A): def __init__(self, normalint): self.normalint = normalint + def meth(self, x): + return self.normalint + x + 2 + class C(A, UnboxedValue): - pass + def meth(self, x): + return self.getvalue() + x + 3 + +# ____________________________________________________________ def test_on_top_of_cpython(): assert C(17).getvalue() == 17 + assert C(20).meth(10) == 33 def test_instantiate(): def fn1(n): @@ -51,3 +60,72 @@ res = interpret(fn2, [sys.maxint]) assert res.item0 == 'B' assert res.item1 == sys.maxint + +def test_prebuilt(): + c = C(111) + def fn(n): + if n < 0: + x = c + else: + x = C(n) + return x.getvalue() + + res = interpret(fn, [12]) + assert res == 12 + res = interpret(fn, [-1]) + assert res == 111 + +def test_C_or_None(): + def g(x): + if x is None: + return sys.maxint + else: + return x.getvalue() + def fn(n): + if n < 0: + x = None + else: + x = C(n) + return g(x) + + res = interpret(fn, [-1]) + assert res == sys.maxint + res = interpret(fn, [56]) + assert res == 56 + +def test_type(): + def fn(n): + if n < 0: + x = B(n) + else: + x = C(n) + return type(x) is B, type(x) is C + + res = interpret(fn, [-212]) + assert res.item0 and not res.item1 + res = interpret(fn, [9874]) + assert res.item1 and not res.item0 + +def test_str(): + def fn(n): + if n > 0: + x = B(n) + else: + x = C(n) + return str(x) + res = interpret(fn, [-832]) + assert ''.join(res.chars) == '' + res = interpret(fn, [1]) + assert ''.join(res.chars) == '' + +def test_method(): + def fn(n): + if n > 0: + x = B(n) + else: + x = C(n) + return x.meth(100) + res = interpret(fn, [1000]) + assert res == 1102 + res = interpret(fn, [-1000]) + assert res == -897 Modified: pypy/dist/pypy/rpython/objectmodel.py ============================================================================== --- pypy/dist/pypy/rpython/objectmodel.py (original) +++ pypy/dist/pypy/rpython/objectmodel.py Fri May 5 22:09:13 2006 @@ -128,6 +128,9 @@ def __init__(self, value): pass + def __repr__(self): + return '' % (self.getvalue(),) + def getvalue(self): return getvalue_from_unboxed(self) From arigo at codespeak.net Fri May 5 23:29:16 2006 From: arigo at codespeak.net (arigo at codespeak.net) Date: Fri, 5 May 2006 23:29:16 +0200 (CEST) Subject: [pypy-svn] r26837 - pypy/dist/pypy/interpreter Message-ID: <20060505212916.07F5510097@code0.codespeak.net> Author: arigo Date: Fri May 5 23:29:16 2006 New Revision: 26837 Modified: pypy/dist/pypy/interpreter/typedef.py Log: A debugging print accidentally checked in. Modified: pypy/dist/pypy/interpreter/typedef.py ============================================================================== --- pypy/dist/pypy/interpreter/typedef.py (original) +++ pypy/dist/pypy/interpreter/typedef.py Fri May 5 23:29:16 2006 @@ -48,7 +48,6 @@ def get_default_hash_function(cls): # go to the first parent class of 'cls' that as a typedef while 'typedef' not in cls.__dict__: - print cls, '=> !' cls = cls.__bases__[0] if cls is object: # not found: 'cls' must have been an abstract class, From arigo at codespeak.net Sat May 6 00:01:23 2006 From: arigo at codespeak.net (arigo at codespeak.net) Date: Sat, 6 May 2006 00:01:23 +0200 (CEST) Subject: [pypy-svn] r26839 - pypy/dist/pypy/translator/backendopt Message-ID: <20060505220123.DD7AB100A0@code0.codespeak.net> Author: arigo Date: Sat May 6 00:01:22 2006 New Revision: 26839 Modified: pypy/dist/pypy/translator/backendopt/inline.py Log: Try to minimize random effects of inlining by making sure we inline all functions up to the threshold. Modified: pypy/dist/pypy/translator/backendopt/inline.py ============================================================================== --- pypy/dist/pypy/translator/backendopt/inline.py (original) +++ pypy/dist/pypy/translator/backendopt/inline.py Sat May 6 00:01:22 2006 @@ -517,7 +517,7 @@ def auto_inlining(translator, multiplier=1, callgraph=None, threshold=BASE_INLINE_THRESHOLD): - from heapq import heappush, heappop, heapreplace + from heapq import heappush, heappop, heapreplace, heapify threshold = threshold * multiplier callers = {} # {graph: {graphs-that-call-it}} callees = {} # {graph: {graphs-that-it-calls}} @@ -543,7 +543,20 @@ continue if weight >= threshold: - break # finished + # finished... unless some graphs not in valid_weight would now + # have a weight below the threshold. Re-insert such graphs + # at the start of the heap + finished = True + for i in range(len(heap)): + graph = heap[i][2] + if not valid_weight.get(graph): + heap[i] = (0.0, heap[i][1], graph) + finished = False + if finished: + break + else: + heapify(heap) + continue heappop(heap) if callers[graph]: From arigo at codespeak.net Sat May 6 00:06:00 2006 From: arigo at codespeak.net (arigo at codespeak.net) Date: Sat, 6 May 2006 00:06:00 +0200 (CEST) Subject: [pypy-svn] r26840 - in pypy/dist/pypy/objspace/std: . test Message-ID: <20060505220600.9B55F10068@code0.codespeak.net> Author: arigo Date: Sat May 6 00:05:47 2006 New Revision: 26840 Modified: pypy/dist/pypy/objspace/std/boolobject.py pypy/dist/pypy/objspace/std/complexobject.py pypy/dist/pypy/objspace/std/complextype.py pypy/dist/pypy/objspace/std/default.py pypy/dist/pypy/objspace/std/dictobject.py pypy/dist/pypy/objspace/std/dictproxyobject.py pypy/dist/pypy/objspace/std/fake.py pypy/dist/pypy/objspace/std/floatobject.py pypy/dist/pypy/objspace/std/floattype.py pypy/dist/pypy/objspace/std/frozensettype.py pypy/dist/pypy/objspace/std/intobject.py pypy/dist/pypy/objspace/std/inttype.py pypy/dist/pypy/objspace/std/iterobject.py pypy/dist/pypy/objspace/std/listobject.py pypy/dist/pypy/objspace/std/listtype.py pypy/dist/pypy/objspace/std/longobject.py pypy/dist/pypy/objspace/std/longtype.py pypy/dist/pypy/objspace/std/marshal_impl.py pypy/dist/pypy/objspace/std/model.py pypy/dist/pypy/objspace/std/multimethod.py pypy/dist/pypy/objspace/std/noneobject.py pypy/dist/pypy/objspace/std/objecttype.py pypy/dist/pypy/objspace/std/objspace.py pypy/dist/pypy/objspace/std/setobject.py pypy/dist/pypy/objspace/std/settype.py pypy/dist/pypy/objspace/std/sliceobject.py pypy/dist/pypy/objspace/std/slicetype.py pypy/dist/pypy/objspace/std/stringobject.py pypy/dist/pypy/objspace/std/stringtype.py pypy/dist/pypy/objspace/std/test/test_complexobject.py pypy/dist/pypy/objspace/std/test/test_floatobject.py pypy/dist/pypy/objspace/std/test/test_intobject.py pypy/dist/pypy/objspace/std/test/test_iterobject.py pypy/dist/pypy/objspace/std/test/test_listobject.py pypy/dist/pypy/objspace/std/test/test_longobject.py pypy/dist/pypy/objspace/std/test/test_multimethod.py pypy/dist/pypy/objspace/std/test/test_sliceobject.py pypy/dist/pypy/objspace/std/test/test_tupleobject.py pypy/dist/pypy/objspace/std/tupleobject.py pypy/dist/pypy/objspace/std/tupletype.py pypy/dist/pypy/objspace/std/typeobject.py pypy/dist/pypy/objspace/std/unicodeobject.py pypy/dist/pypy/objspace/std/unicodetype.py Log: Just for fun, or maybe to try to win the largest diff award: refactored the StdObjSpace to no longer store the 'space' attribute on any of the W_XxxObject classes. It was not really used in any essential way any more. Modified: pypy/dist/pypy/objspace/std/boolobject.py ============================================================================== --- pypy/dist/pypy/objspace/std/boolobject.py (original) +++ pypy/dist/pypy/objspace/std/boolobject.py Sat May 6 00:05:47 2006 @@ -1,12 +1,11 @@ from pypy.objspace.std.objspace import * -from pypy.objspace.std import intobject +from pypy.objspace.std.inttype import wrapint class W_BoolObject(W_Object): from pypy.objspace.std.booltype import bool_typedef as typedef - def __init__(w_self, space, boolval): - W_Object.__init__(w_self, space) + def __init__(w_self, boolval): w_self.boolval = not not boolval def __nonzero__(w_self): @@ -16,15 +15,15 @@ """ representation for debugging purposes """ return "%s(%s)" % (w_self.__class__.__name__, w_self.boolval) - def unwrap(w_self): + def unwrap(w_self, space): return w_self.boolval registerimplementation(W_BoolObject) # bool-to-int delegation requires translating the .boolvar attribute # to an .intval one -def delegate_Bool2Int(w_bool): - return intobject.W_IntObject(w_bool.space, int(w_bool.boolval)) +def delegate_Bool2Int(space, w_bool): + return wrapint(int(w_bool.boolval)) def nonzero__Bool(space, w_bool): Modified: pypy/dist/pypy/objspace/std/complexobject.py ============================================================================== --- pypy/dist/pypy/objspace/std/complexobject.py (original) +++ pypy/dist/pypy/objspace/std/complexobject.py Sat May 6 00:05:47 2006 @@ -13,8 +13,7 @@ from pypy.objspace.std.complextype import complex_typedef as typedef - def __init__(w_self, space, realval=0.0, imgval=0.0): - W_Object.__init__(w_self, space) + def __init__(w_self, realval=0.0, imgval=0.0): w_self.realval = float(realval) w_self.imagval = float(imgval) @@ -111,25 +110,21 @@ -def delegate_Bool2Complex(w_bool): - space = w_bool.space - return W_ComplexObject(space, w_bool.boolval, 0.0) - -def delegate_Int2Complex(w_int): - space = w_int.space - return W_ComplexObject(space, w_int.intval, 0.0) +def delegate_Bool2Complex(space, w_bool): + return W_ComplexObject(w_bool.boolval, 0.0) -def delegate_Long2Complex(w_long): - space = w_long.space +def delegate_Int2Complex(space, w_int): + return W_ComplexObject(w_int.intval, 0.0) + +def delegate_Long2Complex(space, w_long): try: dval = _AsDouble(w_long) except OverflowError, e: raise OperationError(space.w_OverflowError, space.wrap(str(e))) - return W_ComplexObject(space, dval, 0.0) + return W_ComplexObject(dval, 0.0) -def delegate_Float2Complex(w_float): - space = w_float.space - return W_ComplexObject(space, w_float.floatval, 0.0) +def delegate_Float2Complex(space, w_float): + return W_ComplexObject(w_float.floatval, 0.0) def hash__Complex(space, w_value): #this is straight out of CPython complex implementation @@ -151,7 +146,7 @@ return w_complex.realval, w_complex.imagval def _t2w(space, c): - return W_ComplexObject(space, c[0], c[1]) + return W_ComplexObject(c[0], c[1]) def add__Complex_Complex(space, w_complex1, w_complex2): return _t2w(space, _sum(_w2t(space, w_complex1), _w2t(space, w_complex2))) @@ -218,11 +213,11 @@ def neg__Complex(space, w_complex): assert space.is_true(space.isinstance(w_complex, space.w_complex)) - return W_ComplexObject(space, -w_complex.realval, -w_complex.imagval) + return W_ComplexObject(-w_complex.realval, -w_complex.imagval) def pos__Complex(space, w_complex): assert space.is_true(space.isinstance(w_complex, space.w_complex)) - return W_ComplexObject(space, w_complex.realval, w_complex.imagval) + return W_ComplexObject(w_complex.realval, w_complex.imagval) def abs__Complex(space, w_complex): assert space.is_true(space.isinstance(w_complex, space.w_complex)) Modified: pypy/dist/pypy/objspace/std/complextype.py ============================================================================== --- pypy/dist/pypy/objspace/std/complextype.py (original) +++ pypy/dist/pypy/objspace/std/complextype.py Sat May 6 00:05:47 2006 @@ -168,7 +168,7 @@ realval = space.float_w(w_real) imagval = space.float_w(w_imag) w_obj = space.allocate_instance(W_ComplexObject, w_complextype) - W_ComplexObject.__init__(w_obj, space, realval, imagval) + W_ComplexObject.__init__(w_obj, realval, imagval) return w_obj Modified: pypy/dist/pypy/objspace/std/default.py ============================================================================== --- pypy/dist/pypy/objspace/std/default.py (original) +++ pypy/dist/pypy/objspace/std/default.py Sat May 6 00:05:47 2006 @@ -8,8 +8,8 @@ def id__ANY(space, w_obj): #print 'id:', w_obj - from pypy.objspace.std import intobject - return intobject.W_IntObject(space, id(w_obj)) + from pypy.objspace.std.inttype import wrapint + return wrapint(id(w_obj)) # __init__ should succeed if called internally as a multimethod Modified: pypy/dist/pypy/objspace/std/dictobject.py ============================================================================== --- pypy/dist/pypy/objspace/std/dictobject.py (original) +++ pypy/dist/pypy/objspace/std/dictobject.py Sat May 6 00:05:47 2006 @@ -15,7 +15,6 @@ from pypy.objspace.std.dicttype import dict_typedef as typedef def __init__(w_self, space, w_otherdict=None): - W_Object.__init__(w_self, space) if w_otherdict is None: w_self.content = r_dict(space.eq_w, space.hash_w) else: @@ -29,8 +28,7 @@ """ representation for debugging purposes """ return "%s(%s)" % (w_self.__class__.__name__, w_self.content) - def unwrap(w_dict): - space = w_dict.space + def unwrap(w_dict, space): result = {} for w_key, w_value in w_dict.content.items(): # generic mixed types unwrap @@ -43,7 +41,7 @@ def init__Dict(space, w_dict, __args__): w_src, w_kwds = __args__.parse('dict', (['seq_or_map'], None, 'kwargs'), # signature - [W_DictObject(space)]) # default argument + [W_DictObject(space)]) # default argument w_dict.content.clear() try: space.getattr(w_src, space.wrap("keys")) @@ -216,7 +214,7 @@ from pypy.objspace.std.dicttype import dictiter_typedef as typedef def __init__(w_self, space, w_dictobject): - W_Object.__init__(w_self, space) + w_self.space = space w_self.content = content = w_dictobject.content w_self.len = len(content) w_self.pos = 0 Modified: pypy/dist/pypy/objspace/std/dictproxyobject.py ============================================================================== --- pypy/dist/pypy/objspace/std/dictproxyobject.py (original) +++ pypy/dist/pypy/objspace/std/dictproxyobject.py Sat May 6 00:05:47 2006 @@ -1,13 +1,12 @@ from pypy.objspace.std.objspace import * def descr_get_dictproxy(space, w_obj): - return W_DictProxyObject(space, w_obj.getdict()) + return W_DictProxyObject(w_obj.getdict()) class W_DictProxyObject(W_Object): from pypy.objspace.std.dictproxytype import dictproxy_typedef as typedef - def __init__(w_self, space, w_dict): - W_Object.__init__(w_self, space) + def __init__(w_self, w_dict): w_self.w_dict = w_dict registerimplementation(W_DictProxyObject) Modified: pypy/dist/pypy/objspace/std/fake.py ============================================================================== --- pypy/dist/pypy/objspace/std/fake.py (original) +++ pypy/dist/pypy/objspace/std/fake.py Sat May 6 00:05:47 2006 @@ -114,9 +114,8 @@ typedef = StdTypeDef( cpy_type.__name__, base, **kw) def __init__(w_self, space, val): - W_Object.__init__(w_self, space) w_self.val = val - def unwrap(w_self): + def unwrap(w_self, space): return w_self.val # cannot write to W_Fake.__name__ in Python 2.2! Modified: pypy/dist/pypy/objspace/std/floatobject.py ============================================================================== --- pypy/dist/pypy/objspace/std/floatobject.py (original) +++ pypy/dist/pypy/objspace/std/floatobject.py Sat May 6 00:05:47 2006 @@ -20,11 +20,10 @@ an argument""" from pypy.objspace.std.floattype import float_typedef as typedef - def __init__(w_self, space, floatval): - W_Object.__init__(w_self, space) + def __init__(w_self, floatval): w_self.floatval = floatval - def unwrap(w_self): + def unwrap(w_self, space): return w_self.floatval def __repr__(self): @@ -33,20 +32,20 @@ registerimplementation(W_FloatObject) # bool-to-float delegation -def delegate_Bool2Float(w_bool): - return W_FloatObject(w_bool.space, float(w_bool.boolval)) +def delegate_Bool2Float(space, w_bool): + return W_FloatObject(float(w_bool.boolval)) # int-to-float delegation -def delegate_Int2Float(w_intobj): - return W_FloatObject(w_intobj.space, float(w_intobj.intval)) +def delegate_Int2Float(space, w_intobj): + return W_FloatObject(float(w_intobj.intval)) # long-to-float delegation -def delegate_Long2Float(w_longobj): +def delegate_Long2Float(space, w_longobj): try: - return W_FloatObject(w_longobj.space, _AsDouble(w_longobj)) + return W_FloatObject(_AsDouble(w_longobj)) except OverflowError: - raise OperationError(w_longobj.space.w_OverflowError, - w_longobj.space.wrap("long int too large to convert to float")) + raise OperationError(space.w_OverflowError, + space.wrap("long int too large to convert to float")) # float__Float is supposed to do nothing, unless it has @@ -56,7 +55,7 @@ if space.is_w(space.type(w_float1), space.w_float): return w_float1 a = w_float1.floatval - return W_FloatObject(space, a) + return W_FloatObject(a) def int__Float(space, w_value): try: @@ -248,7 +247,7 @@ z = x + y except FloatingPointError: raise FailedToImplement(space.w_FloatingPointError, space.wrap("float addition")) - return W_FloatObject(space, z) + return W_FloatObject(z) def sub__Float_Float(space, w_float1, w_float2): x = w_float1.floatval @@ -257,7 +256,7 @@ z = x - y except FloatingPointError: raise FailedToImplement(space.w_FloatingPointError, space.wrap("float substraction")) - return W_FloatObject(space, z) + return W_FloatObject(z) def mul__Float_Float(space, w_float1, w_float2): x = w_float1.floatval @@ -266,7 +265,7 @@ z = x * y except FloatingPointError: raise FailedToImplement(space.w_FloatingPointError, space.wrap("float multiplication")) - return W_FloatObject(space, z) + return W_FloatObject(z) def div__Float_Float(space, w_float1, w_float2): x = w_float1.floatval @@ -278,7 +277,7 @@ except FloatingPointError: raise FailedToImplement(space.w_FloatingPointError, space.wrap("float division")) # no overflow - return W_FloatObject(space, z) + return W_FloatObject(z) truediv__Float_Float = div__Float_Float @@ -303,7 +302,7 @@ except FloatingPointError: raise FailedToImplement(space.w_FloatingPointError, space.wrap("float division")) - return W_FloatObject(space, mod) + return W_FloatObject(mod) def _divmod_w(space, w_float1, w_float2): x = w_float1.floatval @@ -343,7 +342,7 @@ except FloatingPointError: raise FailedToImplement(space.w_FloatingPointError, space.wrap("float division")) - return [W_FloatObject(space, floordiv), W_FloatObject(space, mod)] + return [W_FloatObject(floordiv), W_FloatObject(mod)] def divmod__Float_Float(space, w_float1, w_float2): return space.newtuple(_divmod_w(space, w_float1, w_float2)) @@ -384,17 +383,17 @@ except ValueError: raise FailedToImplement(space.w_ValueError, space.wrap("float power")) # xxx - return W_FloatObject(space, z) + return W_FloatObject(z) def neg__Float(space, w_float1): - return W_FloatObject(space, -w_float1.floatval) + return W_FloatObject(-w_float1.floatval) def pos__Float(space, w_float): return float__Float(space, w_float) def abs__Float(space, w_float): - return W_FloatObject(space, abs(w_float.floatval)) + return W_FloatObject(abs(w_float.floatval)) def nonzero__Float(space, w_float): return space.newbool(w_float.floatval != 0.0) @@ -405,13 +404,13 @@ if w_float.__class__ == W_FloatObject: return w_float else: - return W_FloatObject(space, w_float.floatval) + return W_FloatObject(w_float.floatval) StdObjSpace.coerce.register(float_coerce, W_FloatObject) """ def getnewargs__Float(space, w_float): - return space.newtuple([W_FloatObject(space, w_float.floatval)]) + return space.newtuple([W_FloatObject(w_float.floatval)]) def log__Float(space, w_float, base): # base is supposed to be positive or 0.0, which means we use e @@ -430,15 +429,15 @@ # pow delegation for negative 2nd arg def pow_neg__Long_Long_None(space, w_int1, w_int2, thirdarg): - w_float1 = delegate_Long2Float(w_int1) - w_float2 = delegate_Long2Float(w_int2) + w_float1 = delegate_Long2Float(space, w_int1) + w_float2 = delegate_Long2Float(space, w_int2) return pow__Float_Float_ANY(space, w_float1, w_float2, thirdarg) StdObjSpace.MM.pow.register(pow_neg__Long_Long_None, W_LongObject, W_LongObject, W_NoneObject, order=1) def pow_neg__Int_Int_None(space, w_int1, w_int2, thirdarg): - w_float1 = delegate_Int2Float(w_int1) - w_float2 = delegate_Int2Float(w_int2) + w_float1 = delegate_Int2Float(space, w_int1) + w_float2 = delegate_Int2Float(space, w_int2) return pow__Float_Float_ANY(space, w_float1, w_float2, thirdarg) StdObjSpace.MM.pow.register(pow_neg__Int_Int_None, W_IntObject, W_IntObject, W_NoneObject, order=2) Modified: pypy/dist/pypy/objspace/std/floattype.py ============================================================================== --- pypy/dist/pypy/objspace/std/floattype.py (original) +++ pypy/dist/pypy/objspace/std/floattype.py Sat May 6 00:05:47 2006 @@ -36,7 +36,7 @@ # whatever x.__float__() returned value = space.float_w(w_obj) w_obj = space.allocate_instance(W_FloatObject, w_floattype) - W_FloatObject.__init__(w_obj, space, value) + W_FloatObject.__init__(w_obj, value) return w_obj # ____________________________________________________________ Modified: pypy/dist/pypy/objspace/std/frozensettype.py ============================================================================== --- pypy/dist/pypy/objspace/std/frozensettype.py (original) +++ pypy/dist/pypy/objspace/std/frozensettype.py Sat May 6 00:05:47 2006 @@ -23,7 +23,7 @@ if _is_frozenset_exact(w_iterable): return w_iterable w_obj = space.allocate_instance(W_FrozensetObject, w_frozensettype) - W_FrozensetObject.__init__(w_obj, space, None) + W_FrozensetObject.__init__(w_obj, None) return w_obj Modified: pypy/dist/pypy/objspace/std/intobject.py ============================================================================== --- pypy/dist/pypy/objspace/std/intobject.py (original) +++ pypy/dist/pypy/objspace/std/intobject.py Sat May 6 00:05:47 2006 @@ -1,6 +1,7 @@ from pypy.objspace.std.objspace import * from pypy.objspace.std.noneobject import W_NoneObject from pypy.rpython.rarithmetic import ovfcheck, ovfcheck_lshift, LONG_BIT, r_uint +from pypy.objspace.std.inttype import wrapint """ In order to have the same behavior running @@ -12,15 +13,14 @@ class W_IntObject(W_Object): from pypy.objspace.std.inttype import int_typedef as typedef - def __init__(w_self, space, intval): - W_Object.__init__(w_self, space) + def __init__(w_self, intval): w_self.intval = intval def __repr__(w_self): """ representation for debugging purposes """ return "%s(%d)" % (w_self.__class__.__name__, w_self.intval) - def unwrap(w_self): + def unwrap(w_self, space): return int(w_self.intval) @@ -53,22 +53,6 @@ str__Int = repr__Int -## deprecated -## we are going to support rich compare, only - -##def int_int_cmp(space, w_int1, w_int2): -## i = w_int1.intval -## j = w_int2.intval -## if i < j: -## ret = -1 -## elif i > j: -## ret = 1 -## else: -## ret = 0 -## return W_IntObject(space, ret) -## -##StdObjSpace.cmp.register(int_int_cmp, W_IntObject, W_IntObject) - def lt__Int_Int(space, w_int1, w_int2): i = w_int1.intval j = w_int2.intval @@ -118,7 +102,7 @@ except OverflowError: raise FailedToImplement(space.w_OverflowError, space.wrap("integer addition")) - return W_IntObject(space, z) + return wrapint(z) def sub__Int_Int(space, w_int1, w_int2): x = w_int1.intval @@ -128,7 +112,7 @@ except OverflowError: raise FailedToImplement(space.w_OverflowError, space.wrap("integer substraction")) - return W_IntObject(space, z) + return wrapint(z) def mul__Int_Int(space, w_int1, w_int2): x = w_int1.intval @@ -138,7 +122,7 @@ except OverflowError: raise FailedToImplement(space.w_OverflowError, space.wrap("integer multiplication")) - return W_IntObject(space, z) + return wrapint(z) def _floordiv(space, w_int1, w_int2): x = w_int1.intval @@ -151,7 +135,7 @@ except OverflowError: raise FailedToImplement(space.w_OverflowError, space.wrap("integer division")) - return W_IntObject(space, z) + return wrapint(z) def _truediv(space, w_int1, w_int2): # XXX how to do delegation to float elegantly? @@ -172,7 +156,7 @@ except OverflowError: raise FailedToImplement(space.w_OverflowError, space.wrap("integer modulo")) - return W_IntObject(space, z) + return wrapint(z) def divmod__Int_Int(space, w_int1, w_int2): x = w_int1.intval @@ -224,7 +208,7 @@ except OverflowError: raise FailedToImplement(space.w_OverflowError, space.wrap("integer exponentiation")) - return W_IntObject(space, ix) + return wrapint(ix) def pow__Int_Int_Int(space, w_int1, w_int2, w_int3): x = w_int1.intval @@ -247,7 +231,7 @@ except OverflowError: raise FailedToImplement(space.w_OverflowError, space.wrap("integer negation")) - return W_IntObject(space, x) + return wrapint(x) # pos__Int is supposed to do nothing, unless it has # a derived integer object, where it should return @@ -267,7 +251,7 @@ def invert__Int(space, w_int1): x = w_int1.intval a = ~x - return W_IntObject(space, a) + return wrapint(a) def lshift__Int_Int(space, w_int1, w_int2): a = w_int1.intval @@ -297,7 +281,7 @@ except OverflowError: raise FailedToImplement(space.w_OverflowError, space.wrap("integer left shift")) - return W_IntObject(space, c) + return wrapint(c) def rshift__Int_Int(space, w_int1, w_int2): a = w_int1.intval @@ -316,25 +300,25 @@ ## please look into pyport.h, how >> should be implemented! ## a = Py_ARITHMETIC_RIGHT_SHIFT(long, a, b); a = a >> b - return W_IntObject(space, a) + return wrapint(a) def and__Int_Int(space, w_int1, w_int2): a = w_int1.intval b = w_int2.intval res = a & b - return W_IntObject(space, res) + return wrapint(res) def xor__Int_Int(space, w_int1, w_int2): a = w_int1.intval b = w_int2.intval res = a ^ b - return W_IntObject(space, res) + return wrapint(res) def or__Int_Int(space, w_int1, w_int2): a = w_int1.intval b = w_int2.intval res = a | b - return W_IntObject(space, res) + return wrapint(res) # coerce is not wanted ## @@ -356,7 +340,7 @@ if space.is_w(space.type(w_int1), space.w_int): return w_int1 a = w_int1.intval - return W_IntObject(space, a) + return wrapint(a) """ # Not registered @@ -378,7 +362,7 @@ return space.wrap(hex(w_int1.intval)) def getnewargs__Int(space, w_int1): - return space.newtuple([W_IntObject(space, w_int1.intval)]) + return space.newtuple([wrapint(w_int1.intval)]) register_all(vars()) Modified: pypy/dist/pypy/objspace/std/inttype.py ============================================================================== --- pypy/dist/pypy/objspace/std/inttype.py (original) +++ pypy/dist/pypy/objspace/std/inttype.py Sat May 6 00:05:47 2006 @@ -3,6 +3,10 @@ from pypy.interpreter.error import OperationError from pypy.interpreter.gateway import NoneNotWrapped +def wrapint(x): + from pypy.objspace.std.intobject import W_IntObject + return W_IntObject(x) + def retry_to_w_long(space, parser, base=0): parser.rewind() try: @@ -83,7 +87,7 @@ return w_longval else: w_obj = space.allocate_instance(W_IntObject, w_inttype) - W_IntObject.__init__(w_obj, space, value) + W_IntObject.__init__(w_obj, value) return w_obj # ____________________________________________________________ Modified: pypy/dist/pypy/objspace/std/iterobject.py ============================================================================== --- pypy/dist/pypy/objspace/std/iterobject.py (original) +++ pypy/dist/pypy/objspace/std/iterobject.py Sat May 6 00:05:47 2006 @@ -10,8 +10,7 @@ class W_SeqIterObject(W_Object): from pypy.objspace.std.itertype import iter_typedef as typedef - def __init__(w_self, space, w_seq, index=0): - W_Object.__init__(w_self, space) + def __init__(w_self, w_seq, index=0): w_self.w_seq = w_seq w_self.index = index @@ -19,7 +18,6 @@ from pypy.objspace.std.itertype import reverse_iter_typedef as typedef def __init__(w_self, space, w_seq, index=-1): - W_Object.__init__(w_self, space) w_self.w_seq = w_seq w_self.w_len = space.len(w_seq) w_self.index = space.int_w(w_self.w_len) + index Modified: pypy/dist/pypy/objspace/std/listobject.py ============================================================================== --- pypy/dist/pypy/objspace/std/listobject.py (original) +++ pypy/dist/pypy/objspace/std/listobject.py Sat May 6 00:05:47 2006 @@ -1,5 +1,5 @@ from pypy.objspace.std.objspace import * -from pypy.objspace.std.intobject import W_IntObject +from pypy.objspace.std.inttype import wrapint from pypy.objspace.std.sliceobject import W_SliceObject from pypy.objspace.std.tupleobject import W_TupleObject @@ -11,16 +11,14 @@ class W_ListObject(W_Object): from pypy.objspace.std.listtype import list_typedef as typedef - def __init__(w_self, space, wrappeditems): - W_Object.__init__(w_self, space) + def __init__(w_self, wrappeditems): w_self.wrappeditems = wrappeditems def __repr__(w_self): """ representation for debugging purposes """ return "%s(%s)" % (w_self.__class__.__name__, w_self.wrappeditems) - def unwrap(w_list): - space = w_list.space + def unwrap(w_list, space): items = [space.unwrap(w_item) for w_item in w_list.wrappeditems]# XXX generic mixed types unwrap return list(items) @@ -28,15 +26,17 @@ registerimplementation(W_ListObject) +EMPTY_LIST = W_ListObject([]) + def init__List(space, w_list, __args__): w_iterable, = __args__.parse('list', (['sequence'], None, None), # signature - [W_ListObject(space, [])]) # default argument + [EMPTY_LIST]) # default argument w_list.wrappeditems = space.unpackiterable(w_iterable) def len__List(space, w_list): result = len(w_list.wrappeditems) - return W_IntObject(space, result) + return wrapint(result) def getitem__List_ANY(space, w_list, w_index): idx = space.int_w(w_index) @@ -49,11 +49,11 @@ def getitem__List_Slice(space, w_list, w_slice): # XXX consider to extend rlist's functionality? length = len(w_list.wrappeditems) - start, stop, step, slicelength = w_slice.indices4(length) + start, stop, step, slicelength = w_slice.indices4(space, length) assert slicelength >= 0 if step == 1 and 0 <= start <= stop: - return W_ListObject(space, w_list.wrappeditems[start:stop]) - w_res = W_ListObject(space, [None] * slicelength) + return W_ListObject(w_list.wrappeditems[start:stop]) + w_res = W_ListObject([None] * slicelength) items_w = w_list.wrappeditems subitems_w = w_res.wrappeditems for i in range(slicelength): @@ -73,10 +73,10 @@ def iter__List(space, w_list): from pypy.objspace.std import iterobject - return iterobject.W_SeqIterObject(space, w_list) + return iterobject.W_SeqIterObject(w_list) def add__List_List(space, w_list1, w_list2): - return W_ListObject(space, w_list1.wrappeditems + w_list2.wrappeditems) + return W_ListObject(w_list1.wrappeditems + w_list2.wrappeditems) def inplace_add__List_ANY(space, w_list1, w_iterable2): list_extend__List_ANY(space, w_list1, w_iterable2) @@ -89,7 +89,7 @@ if e.match(space, space.w_TypeError): raise FailedToImplement raise - return W_ListObject(space, w_list.wrappeditems * times) + return W_ListObject(w_list.wrappeditems * times) def mul__List_ANY(space, w_list, w_times): return mul_list_times(space, w_list, w_times) @@ -164,7 +164,8 @@ return space.w_None def delitem__List_Slice(space, w_list, w_slice): - start, stop, step, slicelength = w_slice.indices4(len(w_list.wrappeditems)) + start, stop, step, slicelength = w_slice.indices4(space, + len(w_list.wrappeditems)) if slicelength==0: return @@ -232,7 +233,7 @@ def _setitem_slice_helper(space, w_list, w_slice, sequence2, len2): oldsize = len(w_list.wrappeditems) - start, stop, step, slicelength = w_slice.indices4(oldsize) + start, stop, step, slicelength = w_slice.indices4(space, oldsize) assert slicelength >= 0 items = w_list.wrappeditems Modified: pypy/dist/pypy/objspace/std/listtype.py ============================================================================== --- pypy/dist/pypy/objspace/std/listtype.py (original) +++ pypy/dist/pypy/objspace/std/listtype.py Sat May 6 00:05:47 2006 @@ -26,7 +26,7 @@ ##''', filename=__file__).interphook('reversed') def list_reversed__ANY(space, w_list): from pypy.objspace.std.iterobject import W_ReverseSeqIterObject - return W_ReverseSeqIterObject(space,w_list,-1) + return W_ReverseSeqIterObject(space, w_list, -1) register_all(vars(), globals()) @@ -35,7 +35,7 @@ def descr__new__(space, w_listtype, __args__): from pypy.objspace.std.listobject import W_ListObject w_obj = space.allocate_instance(W_ListObject, w_listtype) - W_ListObject.__init__(w_obj, space, []) + W_ListObject.__init__(w_obj, []) return w_obj # ____________________________________________________________ Modified: pypy/dist/pypy/objspace/std/longobject.py ============================================================================== --- pypy/dist/pypy/objspace/std/longobject.py (original) +++ pypy/dist/pypy/objspace/std/longobject.py Sat May 6 00:05:47 2006 @@ -86,15 +86,13 @@ # Actually, all methods to be officially used are native implementations. from pypy.objspace.std.longtype import long_typedef as typedef - def __init__(w_self, space, digits, sign=0): - W_Object.__init__(w_self, space) + def __init__(w_self, digits, sign=0): #if isinstance(digits, long): #YYYYYY # digits, sign = args_from_long(digits) if len(digits) == 0: digits = [0] w_self.digits = DigitArray(digits) w_self.sign = sign - w_self.space = space def fromint(space, intval): if intval < 0: @@ -104,7 +102,7 @@ sign = 1 ival = r_uint(intval) else: - return W_LongObject(space, [0], 0) + return W_LongObject([0], 0) # Count the number of Python digits. # We used to pick 5 ("big enough for anything"), but that's a # waste of time and space given that 5*15 = 75 bits are rarely @@ -114,7 +112,7 @@ while t: ndigits += 1 t >>= SHIFT - v = W_LongObject(space, [0] * ndigits, sign) + v = W_LongObject([0] * ndigits, sign) t = ival p = 0 while t: @@ -133,7 +131,7 @@ l += long(d) return l * self.sign - def unwrap(w_self): #YYYYYY + def unwrap(w_self, space): #YYYYYY return w_self.longval() def _normalize(self): @@ -168,13 +166,12 @@ FIVEARY_CUTOFF = 8 # bool-to-long -def delegate_Bool2Long(w_bool): - return W_LongObject(w_bool.space, [w_bool.boolval & MASK], - int(w_bool.boolval)) +def delegate_Bool2Long(space, w_bool): + return W_LongObject([w_bool.boolval & MASK], int(w_bool.boolval)) # int-to-long delegation -def delegate_Int2Long(w_intobj): - return long__Int(w_intobj.space, w_intobj) +def delegate_Int2Long(space, w_intobj): + return long__Int(space, w_intobj) # long__Long is supposed to do nothing, unless it has @@ -185,7 +182,7 @@ return w_long1 digits = w_long1.digits sign = w_long1.sign - return W_LongObject(space, digits, sign) + return W_LongObject(digits, sign) def long__Int(space, w_intobj): return W_LongObject.fromint(space, w_intobj.intval) @@ -328,22 +325,22 @@ return result def truediv__Long_Long(space, w_long1, w_long2): - div = _long_true_divide(w_long1, w_long2) + div = _long_true_divide(space, w_long1, w_long2) return space.newfloat(div) def floordiv__Long_Long(space, w_long1, w_long2): - div, mod = _l_divmod(w_long1, w_long2) + div, mod = _l_divmod(space, w_long1, w_long2) return div def div__Long_Long(space, w_long1, w_long2): return floordiv__Long_Long(space, w_long1, w_long2) def mod__Long_Long(space, w_long1, w_long2): - div, mod = _l_divmod(w_long1, w_long2) + div, mod = _l_divmod(space, w_long1, w_long2) return mod def divmod__Long_Long(space, w_long1, w_long2): - div, mod = _l_divmod(w_long1, w_long2) + div, mod = _l_divmod(space, w_long1, w_long2) return space.newtuple([div, mod]) def _impl_long_long_pow(space, a, b, c=None): @@ -375,24 +372,24 @@ # modulus = -modulus if c.sign < 0: negativeOutput = True - c = W_LongObject(space, c.digits, -c.sign) + c = W_LongObject(c.digits, -c.sign) # if modulus == 1: # return 0 if len(c.digits) == 1 and c.digits[0] == 1: - return W_LongObject(space, [0], 0) + return W_LongObject([0], 0) # if base < 0: # base = base % modulus # Having the base positive just makes things easier. if a.sign < 0: - a, temp = _l_divmod(a, c) + a, temp = _l_divmod(space, a, c) a = temp # At this point a, b, and c are guaranteed non-negative UNLESS # c is NULL, in which case a may be negative. */ - z = W_LongObject(space, [1], 1) + z = W_LongObject([1], 1) # python adaptation: moved macros REDUCE(X) and MULT(X, Y, result) # into helper function result = _help_mult(x, y, c) @@ -404,9 +401,9 @@ bi = b.digits[i] j = 1 << (SHIFT-1) while j != 0: - z = _help_mult(z, z, c) + z = _help_mult(space, z, z, c) if bi & j: - z = _help_mult(z, a, c) + z = _help_mult(space, z, a, c) j >>= 1 i -= 1 else: @@ -415,7 +412,7 @@ table = [z] * 32 table[0] = z; for i in range(1, 32): - table[i] = _help_mult(table[i-1], a, c) + table[i] = _help_mult(space, table[i-1], a, c) i = len(b.digits) - 1 while i >= 0: bi = b.digits[i] @@ -423,26 +420,26 @@ while j >= 0: index = (bi >> j) & 0x1f for k in range(5): - z = _help_mult(z, z, c) + z = _help_mult(space, z, z, c) if index: - z = _help_mult(z, table[index], c) + z = _help_mult(space, z, table[index], c) j -= 5 i -= 1 if negativeOutput and z.sign != 0: - z = sub__Long_Long(z.space, z, c) + z = sub__Long_Long(space, z, c) return z -def _help_mult(x, y, c): +def _help_mult(space, x, y, c): """ Multiply two values, then reduce the result: result = X*Y % c. If c is NULL, skip the mod. """ - res = mul__Long_Long(x.space, x, y) + res = mul__Long_Long(space, x, y) # Perform a modular reduction, X = X % c, but leave X alone if c # is NULL. if c is not None: - res, temp = _l_divmod(res, c) + res, temp = _l_divmod(space, res, c) res = temp return res @@ -454,19 +451,19 @@ def neg__Long(space, w_long1): - return W_LongObject(space, w_long1.digits, -w_long1.sign) + return W_LongObject(w_long1.digits, -w_long1.sign) def pos__Long(space, w_long): return long__Long(space, w_long) def abs__Long(space, w_long): - return W_LongObject(space, w_long.digits, abs(w_long.sign)) + return W_LongObject(w_long.digits, abs(w_long.sign)) def nonzero__Long(space, w_long): return space.newbool(w_long.sign != 0) def invert__Long(space, w_long): #Implement ~x as -(x + 1) - w_lpp = add__Long_Long(space, w_long, W_LongObject(space, [1], 1)) + w_lpp = add__Long_Long(space, w_long, W_LongObject([1], 1)) return neg__Long(space, w_lpp) def lshift__Long_Long(space, w_long1, w_long2): @@ -490,7 +487,7 @@ newsize = oldsize + wordshift if remshift: newsize += 1 - z = W_LongObject(space, [0] * newsize, a.sign) + z = W_LongObject([0] * newsize, a.sign) # not sure if we will initialize things in the future? for i in range(wordshift): z.digits[i] = 0 @@ -530,13 +527,13 @@ wordshift = shiftby // SHIFT newsize = len(a.digits) - wordshift if newsize <= 0: - return W_LongObject(space, [0], 0) + return W_LongObject([0], 0) loshift = shiftby % SHIFT hishift = SHIFT - loshift lomask = (1 << hishift) - 1 himask = MASK ^ lomask - z = W_LongObject(space, [0] * newsize, a.sign) + z = W_LongObject([0] * newsize, a.sign) i = 0 j = wordshift while i < newsize: @@ -549,13 +546,13 @@ return z def and__Long_Long(space, w_long1, w_long2): - return _bitwise(w_long1, '&', w_long2) + return _bitwise(space, w_long1, '&', w_long2) def xor__Long_Long(space, w_long1, w_long2): - return _bitwise(w_long1, '^', w_long2) + return _bitwise(space, w_long1, '^', w_long2) def or__Long_Long(space, w_long1, w_long2): - return _bitwise(w_long1, '|', w_long2) + return _bitwise(space, w_long1, '|', w_long2) def oct__Long(space, w_long1): return space.wrap(_format(w_long1, 8, True)) @@ -564,7 +561,7 @@ return space.wrap(_format(w_long1, 16, True)) def getnewargs__Long(space, w_long1): - return space.newtuple([W_LongObject(space, w_long1.digits, w_long1.sign)]) + return space.newtuple([W_LongObject(w_long1.digits, w_long1.sign)]) def log__Long(space, w_long, base): # base is supposed to be positive or 0.0, which means we use e @@ -584,8 +581,8 @@ for opname in ['add', 'sub', 'mul', 'div', 'floordiv', 'truediv', 'mod', 'divmod', 'lshift']: exec compile(""" def %(opname)s_ovr__Int_Int(space, w_int1, w_int2): - w_long1 = delegate_Int2Long(w_int1) - w_long2 = delegate_Int2Long(w_int2) + w_long1 = delegate_Int2Long(space, w_int1) + w_long2 = delegate_Int2Long(space, w_int2) return %(opname)s__Long_Long(space, w_long1, w_long2) """ % {'opname': opname}, '', 'exec') @@ -595,7 +592,7 @@ for opname in ['neg', 'abs']: exec """ def %(opname)s_ovr__Int(space, w_int1): - w_long1 = delegate_Int2Long(w_int1) + w_long1 = delegate_Int2Long(space, w_int1) return %(opname)s__Long(space, w_long1) """ % {'opname': opname} @@ -603,13 +600,13 @@ # pow def pow_ovr__Int_Int_None(space, w_int1, w_int2, w_none3): - w_long1 = delegate_Int2Long(w_int1) - w_long2 = delegate_Int2Long(w_int2) + w_long1 = delegate_Int2Long(space, w_int1) + w_long2 = delegate_Int2Long(space, w_int2) return pow__Long_Long_None(space, w_long1, w_long2, w_none3) def pow_ovr__Int_Int_Long(space, w_int1, w_int2, w_long3): - w_long1 = delegate_Int2Long(w_int1) - w_long2 = delegate_Int2Long(w_int2) + w_long1 = delegate_Int2Long(space, w_int1) + w_long2 = delegate_Int2Long(space, w_int2) return pow__Long_Long_Long(space, w_long1, w_long2, w_long3) StdObjSpace.MM.pow.register(pow_ovr__Int_Int_None, W_IntObject, W_IntObject, W_NoneObject, order=1) @@ -647,7 +644,7 @@ if size_a < size_b: a, b = b, a size_a, size_b = size_b, size_a - z = W_LongObject(a.space, [0] * (len(a.digits) + 1), 1) + z = W_LongObject([0] * (len(a.digits) + 1), 1) i = 0 carry = 0 while i < size_b: @@ -682,12 +679,12 @@ while i >= 0 and a.digits[i] == b.digits[i]: i -= 1 if i < 0: - return W_LongObject(a.space, [0], 0) + return W_LongObject([0], 0) if a.digits[i] < b.digits[i]: sign = -1 a, b = b, a size_a = size_b = i+1 - z = W_LongObject(a.space, [0] * size_a, 1) + z = W_LongObject([0] * size_a, 1) i = 0 while i < size_b: # The following assumes unsigned arithmetic @@ -718,7 +715,7 @@ size_a = len(a.digits) size_b = len(b.digits) - z = W_LongObject(a.space, [0] * (size_a + size_b), 1) + z = W_LongObject([0] * (size_a + size_b), 1) if a == b: # Efficient squaring per HAC, Algorithm 14.16: # http://www.cacr.math.uwaterloo.ca/hac/about/chap14.pdf @@ -792,8 +789,8 @@ size_n = len(n.digits) size_lo = min(size_n, size) - lo = W_LongObject(n.space, n.digits[:size_lo], 1) - hi = W_LongObject(n.space, n.digits[size_lo:], 1) + lo = W_LongObject(n.digits[:size_lo], 1) + hi = W_LongObject(n.digits[size_lo:], 1) lo._normalize() hi._normalize() return hi, lo @@ -825,7 +822,7 @@ i = KARATSUBA_CUTOFF if asize <= i: if a.sign == 0: - return W_LongObject(a.space, [0], 0) + return W_LongObject([0], 0) else: return _x_mul(a, b) @@ -864,7 +861,7 @@ # at shift. # 1. Allocate result space. - ret = W_LongObject(a.space, [0] * (asize + bsize), 1) + ret = W_LongObject([0] * (asize + bsize), 1) # 2. t1 <- ah*bh, and copy into high digits of result. t1 = _k_mul(ah, bh) @@ -983,12 +980,12 @@ assert 2 * asize <= bsize # Allocate result space, and zero it out. - ret = W_LongObject(a.space, [0] * (asize + bsize), 1) + ret = W_LongObject([0] * (asize + bsize), 1) # Successive slices of b are copied into bslice. - #bslice = W_LongObject(a.space, [0] * asize, 1) + #bslice = W_LongObject([0] * asize, 1) # XXX we cannot pre-allocate, see comments below! - bslice = W_LongObject(a.space, [0], 1) + bslice = W_LongObject([0], 1) nbdone = 0; while bsize > 0: @@ -1041,7 +1038,7 @@ """ assert n > 0 and n <= MASK size = len(a.digits) - z = W_LongObject(a.space, [0] * size, 1) + z = W_LongObject([0] * size, 1) rem = _inplace_divrem1(z, a, n) z._normalize() return z, rem @@ -1105,7 +1102,7 @@ """Multiply by a single digit and add a single digit, ignoring the sign. """ size_a = len(a.digits) - z = W_LongObject(a.space, [0] * (size_a+1), 1) + z = W_LongObject([0] * (size_a+1), 1) carry = extra assert carry & MASK == carry i = 0 @@ -1130,7 +1127,7 @@ assert size_v >= size_w and size_w > 1 # Assert checks by div() size_a = size_v - size_w + 1 - a = W_LongObject(v.space, [0] * size_a, 1) + a = W_LongObject([0] * size_a, 1) j = size_v k = size_a - 1 @@ -1192,25 +1189,25 @@ return a, rem -def _divrem(a, b): +def _divrem(space, a, b): """ Long division with remainder, top-level routine """ size_a = len(a.digits) size_b = len(b.digits) if b.sign == 0: - raise OperationError(a.space.w_ZeroDivisionError, - a.space.wrap("long division or modulo by zero")) + raise OperationError(space.w_ZeroDivisionError, + space.wrap("long division or modulo by zero")) if (size_a < size_b or (size_a == size_b and a.digits[size_a-1] < b.digits[size_b-1])): # |a| < |b| - z = W_LongObject(a.space, [0], 0) + z = W_LongObject([0], 0) rem = a return z, rem if size_b == 1: z, urem = _divrem1(a, b.digits[0]) - rem = W_LongObject(a.space, [urem], int(urem != 0)) + rem = W_LongObject([urem], int(urem != 0)) else: z, rem = _x_divrem(a, b) # Set the signs. @@ -1304,13 +1301,13 @@ return func(x) + (e * float(SHIFT) * func(2.0)) _loghelper._annspecialcase_ = 'specialize:arg(0)' -def _long_true_divide(a, b): +def _long_true_divide(space, a, b): try: ad, aexp = _AsScaledDouble(a) bd, bexp = _AsScaledDouble(b) if bd == 0.0: - raise OperationError(a.space.w_ZeroDivisionError, - a.space.wrap("long division or modulo by zero")) + raise OperationError(space.w_ZeroDivisionError, + space.wrap("long division or modulo by zero")) # True value is very close to ad/bd * 2**(SHIFT*(aexp-bexp)) ad /= bd # overflow/underflow impossible here @@ -1325,8 +1322,8 @@ # math.ldexp checks and raises return ad except OverflowError: - raise OperationError(a.space.w_OverflowError, - a.space.wrap("long/long too large for a float")) + raise OperationError(space.w_OverflowError, + space.wrap("long/long too large for a float")) def _FromDouble(space, dval): @@ -1339,9 +1336,9 @@ dval = -dval frac, expo = math.frexp(dval) # dval = frac*2**expo; 0.0 <= frac < 1.0 if expo <= 0: - return W_LongObject(space, [0], 0) + return W_LongObject([0], 0) ndig = (expo-1) // SHIFT + 1 # Number of 'digits' in result - v = W_LongObject(space, [0] * ndig, 1) + v = W_LongObject([0] * ndig, 1) frac = math.ldexp(frac, (expo-1) % SHIFT + 1) for i in range(ndig-1, -1, -1): bits = int(frac) & MASK # help the future annotator? @@ -1352,7 +1349,7 @@ v.sign = -1 return v -def _l_divmod(v, w): +def _l_divmod(space, v, w): """ The / and % operators are now defined in terms of divmod(). The expression a mod b has the value a - b*floor(a/b). @@ -1369,11 +1366,11 @@ have different signs. We then subtract one from the 'div' part of the outcome to keep the invariant intact. """ - div, mod = _divrem(v, w) + div, mod = _divrem(space, v, w) if mod.sign * w.sign == -1: - mod = add__Long_Long(v.space, mod, w) - one = W_LongObject(v.space, [1], 1) - div = sub__Long_Long(v.space, div, one) + mod = add__Long_Long(space, mod, w) + one = W_LongObject([1], 1) + div = sub__Long_Long(space, div, one) return div, mod @@ -1457,7 +1454,7 @@ power += 1 # Get a scratch area for repeated division. - scratch = W_LongObject(a.space, [0] * size, 1) + scratch = W_LongObject([0] * size, 1) # Repeatedly divide by powbase. while 1: @@ -1518,16 +1515,16 @@ return ''.join(s[p:]) -def _bitwise(a, op, b): # '&', '|', '^' +def _bitwise(space, a, op, b): # '&', '|', '^' """ Bitwise and/or/xor operations """ if a.sign < 0: - a = invert__Long(a.space, a) + a = invert__Long(space, a) maska = MASK else: maska = 0 if b.sign < 0: - b = invert__Long(b.space, b) + b = invert__Long(space, b) maskb = MASK else: maskb = 0 @@ -1572,7 +1569,7 @@ else: size_z = max(size_a, size_b) - z = W_LongObject(a.space, [0] * size_z, 1) + z = W_LongObject([0] * size_z, 1) for i in range(size_z): if i < size_a: @@ -1593,7 +1590,7 @@ z._normalize() if negz == 0: return z - return invert__Long(z.space, z) + return invert__Long(space, z) def _AsLong(v): """ Modified: pypy/dist/pypy/objspace/std/longtype.py ============================================================================== --- pypy/dist/pypy/objspace/std/longtype.py (original) +++ pypy/dist/pypy/objspace/std/longtype.py Sat May 6 00:05:47 2006 @@ -42,7 +42,7 @@ sign = 1 else: sign = 0 - w_value = W_LongObject(space, [abs(intval)], sign) + w_value = W_LongObject([abs(intval)], sign) else: raise OperationError(space.w_ValueError, space.wrap("value can't be converted to long")) @@ -66,7 +66,7 @@ space.wrap(e.msg)) w_obj = space.allocate_instance(W_LongObject, w_longtype) - W_LongObject.__init__(w_obj, space, w_value.digits, w_value.sign) + W_LongObject.__init__(w_obj, w_value.digits, w_value.sign) return w_obj # ____________________________________________________________ Modified: pypy/dist/pypy/objspace/std/marshal_impl.py ============================================================================== --- pypy/dist/pypy/objspace/std/marshal_impl.py (original) +++ pypy/dist/pypy/objspace/std/marshal_impl.py Sat May 6 00:05:47 2006 @@ -11,6 +11,7 @@ from pypy.interpreter.error import OperationError from pypy.objspace.std.register_all import register_all from pypy.rpython.rarithmetic import LONG_BIT +from pypy.objspace.std.inttype import wrapint from pypy.objspace.std.floatobject import repr__Float as repr_float from pypy.objspace.std.longobject import SHIFT as long_bits from pypy.objspace.std.objspace import StdObjSpace @@ -141,14 +142,14 @@ m.atom_int(TYPE_INT, w_int.intval) def unmarshal_Int(space, u, tc): - return W_IntObject(space, u.get_int()) + return wrapint(u.get_int()) register(TYPE_INT, unmarshal_Int) def unmarshal_Int64(space, u, tc): if LONG_BIT >= 64: lo = u.get_int() & (2**32-1) hi = u.get_int() - return W_IntObject(space, (hi << 32) | lo) + return wrapint((hi << 32) | lo) else: # fall back to a long # XXX at some point, we need to extend longobject @@ -198,7 +199,7 @@ def unmarshal_Float(space, u, tc): if tc == TYPE_BINARY_FLOAT: w_ret = str_to_float(space, space.wrap(u.get(8))) - return W_FloatObject(space, space.float_w(w_ret)) + return W_FloatObject(space.float_w(w_ret)) else: return space.call_function(space.builtin.get('float'), space.wrap(u.get_pascal())) @@ -266,7 +267,7 @@ raise_exception(space, 'bad marshal data') digits[i] = digit i += 1 - w_long = W_LongObject(space, digits, sign) + w_long = W_LongObject(digits, sign) w_long._normalize() return w_long register(TYPE_LONG, unmarshal_Long) @@ -283,7 +284,7 @@ # using the fastest possible access method here # that does not touch the internal representation, # which might change (array of bytes?) - s = w_str.unwrap() + s = w_str.unwrap(space) if m.version >= 1 and PySTRING_CHECK_INTERNED(w_str): # we use a native rtyper stringdict for speed idx = m.stringtable.get(s, -1) @@ -297,11 +298,11 @@ m.atom_str(TYPE_STRING, s) def unmarshal_String(space, u, tc): - return W_StringObject(space, u.get_str()) + return W_StringObject(u.get_str()) register(TYPE_STRING, unmarshal_String) def unmarshal_interned(space, u, tc): - w_ret = W_StringObject(space, u.get_str()) + w_ret = W_StringObject(u.get_str()) u.stringtable_w.append(w_ret) w_intern = space.builtin.get('intern') space.call_function(w_intern, w_ret) @@ -323,7 +324,7 @@ def unmarshal_Tuple(space, u, tc): items_w = u.get_list_w() - return W_TupleObject(space, items_w) + return W_TupleObject(items_w) register(TYPE_TUPLE, unmarshal_Tuple) def marshal_w__List(space, w_list, m): @@ -333,10 +334,10 @@ def unmarshal_List(space, u, tc): items_w = u.get_list_w() - return W_ListObject(space, items_w) + return W_ListObject(items_w) def finish_List(space, items_w, typecode): - return W_ListObject(space, items_w) + return W_ListObject(items_w) register(TYPE_LIST, unmarshal_List) def marshal_w__Dict(space, w_dict, m): @@ -467,7 +468,7 @@ string_to_buffer = app.interphook('string_to_buffer') def unmarshal_buffer(space, u, tc): - w_s = W_StringObject(space, u.get_str()) + w_s = W_StringObject(u.get_str()) return string_to_buffer(space, w_s) register(TYPE_UNKNOWN, unmarshal_buffer) @@ -510,7 +511,7 @@ w_frozen = space.w_False else: w_frozen = space.w_True - w_lis = W_ListObject(space, items_w) + w_lis = W_ListObject(items_w) return list_to_set(space, w_lis, w_frozen) register(TYPE_SET + TYPE_FROZENSET, unmarshal_set_frozenset) Modified: pypy/dist/pypy/objspace/std/model.py ============================================================================== --- pypy/dist/pypy/objspace/std/model.py (original) +++ pypy/dist/pypy/objspace/std/model.py Sat May 6 00:05:47 2006 @@ -138,14 +138,10 @@ W_ANY = W_Root -class W_Object(W_Root, object): - "Parent base class for wrapped objects." - - def __init__(w_self, space): - w_self.space = space # XXX not sure this is ever used any more - # Note that it is wrong to depend on a .space attribute for a random - # wrapped object anyway, because not all wrapped objects inherit from - # W_Object. (They inherit from W_Root.) +class W_Object(W_Root): + "Parent base class for wrapped objects provided by the StdObjSpace." + # Note that not all wrapped objects in the interpreter inherit from + # W_Object. (They inherit from W_Root.) def __repr__(self): s = '%s(%s)' % ( @@ -158,7 +154,7 @@ s += ' instance of %s' % self.w__class__ return '<%s>' % s - def unwrap(w_self): + def unwrap(w_self, space): raise UnwrapError, 'cannot unwrap %r' % (w_self,) class UnwrapError(Exception): Modified: pypy/dist/pypy/objspace/std/multimethod.py ============================================================================== --- pypy/dist/pypy/objspace/std/multimethod.py (original) +++ pypy/dist/pypy/objspace/std/multimethod.py Sat May 6 00:05:47 2006 @@ -214,8 +214,10 @@ callargs = funcargs[:] if conversion is not None: to_convert = func_selfarg_index + convert_callargs = (self.multimethod.argnames_before + + [callargs[to_convert]]) callargs[to_convert] = '%s(%s)' % ( - invent_name(conversion), callargs[to_convert]) + invent_name(conversion), ', '.join(convert_callargs)) callname = invent_name(call) if call_selfarg_index is not None: # fallback on root_class Modified: pypy/dist/pypy/objspace/std/noneobject.py ============================================================================== --- pypy/dist/pypy/objspace/std/noneobject.py (original) +++ pypy/dist/pypy/objspace/std/noneobject.py Sat May 6 00:05:47 2006 @@ -9,7 +9,7 @@ class W_NoneObject(W_Object): from pypy.objspace.std.nonetype import none_typedef as typedef - def unwrap(w_self): + def unwrap(w_self, space): return None registerimplementation(W_NoneObject) Modified: pypy/dist/pypy/objspace/std/objecttype.py ============================================================================== --- pypy/dist/pypy/objspace/std/objecttype.py (original) +++ pypy/dist/pypy/objspace/std/objecttype.py Sat May 6 00:05:47 2006 @@ -51,7 +51,7 @@ space.wrap("default __new__ takes " "no parameters")) w_obj = space.allocate_instance(W_ObjectObject, w_type) - W_ObjectObject.__init__(w_obj, space) + #W_ObjectObject.__init__(w_obj) return w_obj def descr__init__(space, w_obj, __args__): Modified: pypy/dist/pypy/objspace/std/objspace.py ============================================================================== --- pypy/dist/pypy/objspace/std/objspace.py (original) +++ pypy/dist/pypy/objspace/std/objspace.py Sat May 6 00:05:47 2006 @@ -79,11 +79,13 @@ # hack to avoid imports in the time-critical functions below for cls in self.model.typeorder: globals()[cls.__name__] = cls + from pypy.objspace.std.inttype import wrapint + self.newint = wrapint # singletons - self.w_None = W_NoneObject(self) - self.w_False = W_BoolObject(self, False) - self.w_True = W_BoolObject(self, True) + self.w_None = W_NoneObject() + self.w_False = W_BoolObject(False) + self.w_True = W_BoolObject(True) from pypy.interpreter.special import NotImplemented, Ellipsis self.w_NotImplemented = self.wrap(NotImplemented(self)) self.w_Ellipsis = self.wrap(Ellipsis(self)) @@ -259,53 +261,54 @@ raise TypeError, ("attempt to wrap already wrapped exception: %s"% (x,)) if isinstance(x, int): - if isinstance(bool, type) and isinstance(x, bool): + if isinstance(x, bool): return self.newbool(x) - return W_IntObject(self, x) + else: + return self.newint(x) if isinstance(x, str): - return W_StringObject(self, x) + return W_StringObject(x) if isinstance(x, unicode): - return W_UnicodeObject(self, [unichr(ord(u)) for u in x]) # xxx + return W_UnicodeObject([unichr(ord(u)) for u in x]) # xxx if isinstance(x, dict): items_w = [(self.wrap(k), self.wrap(v)) for (k, v) in x.iteritems()] return self.newdict(items_w) if isinstance(x, float): - return W_FloatObject(self, x) + return W_FloatObject(x) if isinstance(x, tuple): wrappeditems = [self.wrap(item) for item in list(x)] - return W_TupleObject(self, wrappeditems) + return W_TupleObject(wrappeditems) if isinstance(x, list): wrappeditems = [self.wrap(item) for item in x] - return W_ListObject(self, wrappeditems) + return W_ListObject(wrappeditems) if isinstance(x, Wrappable): w_result = x.__spacebind__(self) #print 'wrapping', x, '->', w_result return w_result if isinstance(x, base_int): from pypy.objspace.std.longobject import args_from_long - return W_LongObject(self, *args_from_long(x)) + return W_LongObject(*args_from_long(x)) # _____ below here is where the annotator should not get _____ if isinstance(x, long): from pypy.objspace.std.longobject import args_from_long - return W_LongObject(self, *args_from_long(x)) + return W_LongObject(*args_from_long(x)) if isinstance(x, slice): - return W_SliceObject(self, self.wrap(x.start), - self.wrap(x.stop), - self.wrap(x.step)) + return W_SliceObject(self.wrap(x.start), + self.wrap(x.stop), + self.wrap(x.step)) if isinstance(x, complex): - return W_ComplexObject(self, x.real, x.imag) + return W_ComplexObject(x.real, x.imag) if isinstance(x, set): if WITHSET: wrappeditems = [self.wrap(item) for item in x] - return W_SetObject(self, wrappeditems) + return W_SetObject(wrappeditems) if isinstance(x, frozenset): if WITHSET: wrappeditems = [self.wrap(item) for item in x] - return W_FrozensetObject(self, wrappeditems) + return W_FrozensetObject(wrappeditems) if x is __builtin__.Ellipsis: # '__builtin__.Ellipsis' avoids confusion with special.Ellipsis @@ -340,35 +343,35 @@ if isinstance(w_obj, Wrappable): return w_obj if isinstance(w_obj, W_Object): - return w_obj.unwrap() + return w_obj.unwrap(self) raise UnwrapError, "cannot unwrap: %r" % w_obj - - def newint(self, intval): - return W_IntObject(self, intval) + #def newint(self, intval): + # this time-critical and circular-imports-funny method is stored + # on 'self' by initialize() def newfloat(self, floatval): - return W_FloatObject(self, floatval) + return W_FloatObject(floatval) def newcomplex(self, realval, imagval): - return W_ComplexObject(self, realval, imagval) + return W_ComplexObject(realval, imagval) if WITHSET: def newset(self, rdict_w): - return W_SetObject(self, rdict_w) + return W_SetObject(rdict_w) def newfrozenset(self, rdict_w): - return W_FrozensetObject(self, rdict_w) + return W_FrozensetObject(rdict_w) def newlong(self, val): # val is an int return W_LongObject.fromint(self, val) def newtuple(self, list_w): assert isinstance(list_w, list) - return W_TupleObject(self, list_w) + return W_TupleObject(list_w) def newlist(self, list_w): - return W_ListObject(self, list_w) + return W_ListObject(list_w) def newdict(self, list_pairs_w): w_result = W_DictObject(self) @@ -376,7 +379,7 @@ return w_result def newslice(self, w_start, w_end, w_step): - return W_SliceObject(self, w_start, w_end, w_step) + return W_SliceObject(w_start, w_end, w_step) def newstring(self, chars_w): try: @@ -384,7 +387,7 @@ except ValueError: # chr(out-of-range) raise OperationError(self.w_ValueError, self.wrap("character code not in range(256)")) - return W_StringObject(self, ''.join(chars)) + return W_StringObject(''.join(chars)) def newunicode(self, chars): try: @@ -392,10 +395,10 @@ except ValueError, e: # unichr(out-of-range) msg = "character code not in range(%s)" % hex(sys.maxunicode+1) raise OperationError(self.w_ValueError, self.wrap(msg)) - return W_UnicodeObject(self, chars) + return W_UnicodeObject(chars) def newseqiter(self, w_obj): - return W_SeqIterObject(self, w_obj) + return W_SeqIterObject(w_obj) def type(self, w_obj): return w_obj.getclass(self) Modified: pypy/dist/pypy/objspace/std/setobject.py ============================================================================== --- pypy/dist/pypy/objspace/std/setobject.py (original) +++ pypy/dist/pypy/objspace/std/setobject.py Sat May 6 00:05:47 2006 @@ -8,8 +8,7 @@ class W_BaseSetObject(W_Object): - def __init__(w_self, space, setdata=None): - W_Object.__init__(w_self, space) + def __init__(w_self, setdata=None): if setdata is None: w_self.setdata = r_dict(space.eq_w, space.hash_w) else: @@ -21,28 +20,25 @@ return "<%s(%s)>" % (w_self.__class__.__name__, ', '.join(reprlist)) def _newobj(w_self, space, rdict_w=None): - #return space.call(space.type(w_self),W_SetIterObject(space,rdict_w)) + #return space.call(space.type(w_self),W_SetIterObject(rdict_w)) objtype = type(w_self) if objtype is W_SetObject: - obj = W_SetObject(space, rdict_w) + obj = W_SetObject(rdict_w) elif objtype is W_FrozensetObject: - obj = W_FrozensetObject(space, rdict_w) + obj = W_FrozensetObject(rdict_w) else: - itemiterator = space.iter(W_SetIterObject(space,rdict_w)) + itemiterator = space.iter(W_SetIterObject(rdict_w)) obj = space.call_function(space.type(w_self),itemiterator) return obj class W_SetObject(W_BaseSetObject): from pypy.objspace.std.settype import set_typedef as typedef - def __init__(w_self, space, setdata=None): - W_BaseSetObject.__init__(w_self, space, setdata) - class W_FrozensetObject(W_BaseSetObject): from pypy.objspace.std.frozensettype import frozenset_typedef as typedef - def __init__(w_self, space, setdata): - W_BaseSetObject.__init__(w_self, space, setdata) + def __init__(w_self, setdata): + W_BaseSetObject.__init__(w_self, setdata) w_self.hash = -1 registerimplementation(W_SetObject) @@ -51,8 +47,7 @@ class W_SetIterObject(W_Object): from pypy.objspace.std.settype import setiter_typedef as typedef - def __init__(w_self, space, setdata): - W_Object.__init__(w_self, space) + def __init__(w_self, setdata): w_self.content = content = setdata w_self.len = len(content) w_self.pos = 0 @@ -525,7 +520,7 @@ len__Frozenset = len__Set def iter__Set(space, w_left): - return W_SetIterObject(space, w_left.setdata) + return W_SetIterObject(w_left.setdata) iter__Frozenset = iter__Set Modified: pypy/dist/pypy/objspace/std/settype.py ============================================================================== --- pypy/dist/pypy/objspace/std/settype.py (original) +++ pypy/dist/pypy/objspace/std/settype.py Sat May 6 00:05:47 2006 @@ -29,7 +29,7 @@ def descr__new__(space, w_settype, __args__): from pypy.objspace.std.setobject import W_SetObject w_obj = space.allocate_instance(W_SetObject, w_settype) - W_SetObject.__init__(w_obj, space, None) + W_SetObject.__init__(w_obj, None) return w_obj set_typedef = StdTypeDef("set", Modified: pypy/dist/pypy/objspace/std/sliceobject.py ============================================================================== --- pypy/dist/pypy/objspace/std/sliceobject.py (original) +++ pypy/dist/pypy/objspace/std/sliceobject.py Sat May 6 00:05:47 2006 @@ -13,8 +13,7 @@ class W_SliceObject(W_Object): from pypy.objspace.std.slicetype import slice_typedef as typedef - def __init__(w_self, space, w_start, w_stop, w_step): - W_Object.__init__(w_self, space) + def __init__(w_self, w_start, w_stop, w_step): assert w_start is not None assert w_stop is not None assert w_step is not None @@ -22,12 +21,10 @@ w_self.w_stop = w_stop w_self.w_step = w_step - def unwrap(w_slice): - space = w_slice.space + def unwrap(w_slice, space): return slice(space.unwrap(w_slice.w_start), space.unwrap(w_slice.w_stop), space.unwrap(w_slice.w_step)) - def indices3(w_slice, length): - space = w_slice.space + def indices3(w_slice, space, length): if space.is_w(w_slice.w_step, space.w_None): step = 1 else: @@ -69,8 +66,8 @@ stop = length return start, stop, step - def indices4(w_slice, length): - start, stop, step = w_slice.indices3(length) + def indices4(w_slice, space, length): + start, stop, step = w_slice.indices3(space, length) if (step < 0 and stop >= start) or (step > 0 and start >= stop): slicelength = 0 elif step < 0: @@ -115,7 +112,7 @@ def slice_indices__Slice_ANY(space, w_slice, w_length): length = space.int_w(w_length) - start, stop, step = w_slice.indices3(length) + start, stop, step = w_slice.indices3(space, length) return space.newtuple([space.wrap(start), space.wrap(stop), space.wrap(step)]) Modified: pypy/dist/pypy/objspace/std/slicetype.py ============================================================================== --- pypy/dist/pypy/objspace/std/slicetype.py (original) +++ pypy/dist/pypy/objspace/std/slicetype.py Sat May 6 00:05:47 2006 @@ -56,7 +56,7 @@ raise OperationError(space.w_TypeError, space.wrap("slice() takes at least 1 argument")) w_obj = space.allocate_instance(W_SliceObject, w_slicetype) - W_SliceObject.__init__(w_obj, space, w_start, w_stop, w_step) + W_SliceObject.__init__(w_obj, w_start, w_stop, w_step) return w_obj # descr__new__.unwrap_spec = [baseobjspace.ObjSpace, baseobjspace.W_Root, Modified: pypy/dist/pypy/objspace/std/stringobject.py ============================================================================== --- pypy/dist/pypy/objspace/std/stringobject.py (original) +++ pypy/dist/pypy/objspace/std/stringobject.py Sat May 6 00:05:47 2006 @@ -4,7 +4,7 @@ from pypy.interpreter import gateway from pypy.rpython.rarithmetic import ovfcheck, _hash_string from pypy.rpython.objectmodel import we_are_translated -from pypy.objspace.std.intobject import W_IntObject +from pypy.objspace.std.inttype import wrapint from pypy.objspace.std.sliceobject import W_SliceObject from pypy.objspace.std import slicetype from pypy.objspace.std.listobject import W_ListObject @@ -18,23 +18,21 @@ class W_StringObject(W_Object): from pypy.objspace.std.stringtype import str_typedef as typedef - def __init__(w_self, space, str): - W_Object.__init__(w_self, space) + def __init__(w_self, str): w_self._value = str def __repr__(w_self): """ representation for debugging purposes """ return "%s(%r)" % (w_self.__class__.__name__, w_self._value) - def unwrap(w_self): + def unwrap(w_self, space): return w_self._value registerimplementation(W_StringObject) -def _is_generic(w_self, fun): - space = w_self.space +def _is_generic(space, w_self, fun): v = w_self._value if len(v) == 0: return space.w_False @@ -46,7 +44,7 @@ if not fun(v[idx]): return space.w_False return space.w_True -_is_generic._annspecialcase_ = "specialize:arg(1)" +_is_generic._annspecialcase_ = "specialize:arg(2)" def _upper(ch): if ch.islower(): @@ -68,21 +66,20 @@ _isalnum = lambda c: c.isalnum() def str_isspace__String(space, w_self): - return _is_generic(w_self, _isspace) + return _is_generic(space, w_self, _isspace) def str_isdigit__String(space, w_self): - return _is_generic(w_self, _isdigit) + return _is_generic(space, w_self, _isdigit) def str_isalpha__String(space, w_self): - return _is_generic(w_self, _isalpha) + return _is_generic(space, w_self, _isalpha) def str_isalnum__String(space, w_self): - return _is_generic(w_self, _isalnum) + return _is_generic(space, w_self, _isalnum) def str_isupper__String(space, w_self): """Return True if all cased characters in S are uppercase and there is at least one cased character in S, False otherwise.""" - space = w_self.space v = w_self._value if len(v) == 1: c = v[0] @@ -98,7 +95,6 @@ def str_islower__String(space, w_self): """Return True if all cased characters in S are lowercase and there is at least one cased character in S, False otherwise.""" - space = w_self.space v = w_self._value if len(v) == 1: c = v[0] @@ -233,12 +229,12 @@ maxsplit -= 1 # NB. if it's already < 0, it stays < 0 # the word is value[i:j] - res_w.append(W_StringObject(space, value[i:j])) + res_w.append(W_StringObject(value[i:j])) # continue to look from the character following the space after the word i = j + 1 - return W_ListObject(space, res_w) + return W_ListObject(res_w) def str_split__String_String_ANY(space, w_self, w_by, w_maxsplit=-1): @@ -255,13 +251,13 @@ next = value.find(by, start) if next < 0: break - res_w.append(W_StringObject(space, value[start:next])) + res_w.append(W_StringObject(value[start:next])) start = next + bylen maxsplit -= 1 # NB. if it's already < 0, it stays < 0 - res_w.append(W_StringObject(space, value[start:])) + res_w.append(W_StringObject(value[start:])) - return W_ListObject(w_self.space, res_w) + return W_ListObject(res_w) def str_rsplit__String_None_ANY(space, w_self, w_none, w_maxsplit=-1): maxsplit = space.int_w(w_maxsplit) @@ -290,13 +286,13 @@ # the word is value[j+1:i+1] j1 = j + 1 assert j1 >= 0 - res_w.append(W_StringObject(space, value[j1:i+1])) + res_w.append(W_StringObject(value[j1:i+1])) # continue to look from the character before the space before the word i = j - 1 res_w.reverse() - return W_ListObject(space, res_w) + return W_ListObject(res_w) def str_rsplit__String_String_ANY(space, w_self, w_by, w_maxsplit=-1): maxsplit = space.int_w(w_maxsplit) @@ -312,13 +308,13 @@ next = value.rfind(by, 0, end) if next < 0: break - res_w.append(W_StringObject(space, value[next+bylen:end])) + res_w.append(W_StringObject(value[next+bylen:end])) end = next maxsplit -= 1 # NB. if it's already < 0, it stays < 0 - res_w.append(W_StringObject(space, value[:end])) + res_w.append(W_StringObject(value[:end])) res_w.reverse() - return W_ListObject(w_self.space, res_w) + return W_ListObject(res_w) def str_join__String_ANY(space, w_self, w_list): list = space.unpackiterable(w_list) @@ -622,7 +618,7 @@ else: u_centered = u_self - return W_StringObject(space, u_centered) + return W_StringObject(u_centered) def str_count__String_String_ANY_ANY(space, w_self, w_arg, w_start, w_end): u_self = w_self._value @@ -646,7 +642,7 @@ count += 1 u_start = pos + len(u_arg) - return W_IntObject(space, count) + return wrapint(count) def str_endswith__String_String_ANY_ANY(space, w_self, w_suffix, w_start, w_end): @@ -713,7 +709,7 @@ u_expanded += " " * _tabindent(oldtoken,u_tabsize) + token oldtoken = token - return W_StringObject(space, u_expanded) + return W_StringObject(u_expanded) def str_splitlines__String_ANY(space, w_self, w_keepends): @@ -734,13 +730,13 @@ i += 1 if u_keepends: eol = i - L.append(W_StringObject(space, data[j:eol])) + L.append(W_StringObject(data[j:eol])) j = i if j < selflen: - L.append(W_StringObject(space, data[j:])) + L.append(W_StringObject(data[j:])) - return W_ListObject(space, L) + return W_ListObject(L) def str_zfill__String_ANY(space, w_self, w_width): input = w_self._value @@ -779,7 +775,7 @@ x = _hash_string(s) # to make sure we get the same hash as rpython # (otherwise translation will freeze W_DictObjects where we can't find # the keys any more!) - return W_IntObject(space, x) + return wrapint(x) def lt__String_String(space, w_str1, w_str2): s1 = w_str1._value @@ -839,13 +835,13 @@ exc = space.call_function(space.w_IndexError, space.wrap("string index out of range")) raise OperationError(space.w_IndexError, exc) - return W_StringObject(space, str[ival]) + return W_StringObject(str[ival]) def getitem__String_Slice(space, w_str, w_slice): w = space.wrap s = w_str._value length = len(s) - start, stop, step, sl = w_slice.indices4(length) + start, stop, step, sl = w_slice.indices4(space, length) if sl == 0: str = "" elif step == 1: @@ -853,7 +849,7 @@ str = s[start:stop] else: str = "".join([s[start + i*step] for i in range(sl)]) - return W_StringObject(space, str) + return W_StringObject(str) def _makebuf(length): """This helper needs to be a separate function so that we can safely @@ -908,11 +904,11 @@ def str__String(space, w_str): if type(w_str) is W_StringObject: return w_str - return W_StringObject(space, w_str._value) + return W_StringObject(w_str._value) def iter__String(space, w_list): from pypy.objspace.std import iterobject - return iterobject.W_SeqIterObject(space, w_list) + return iterobject.W_SeqIterObject(w_list) def ord__String(space, w_str): u_str = w_str._value @@ -924,7 +920,7 @@ return space.wrap(ord(u_str)) def getnewargs__String(space, w_str): - return space.newtuple([W_StringObject(space, w_str._value)]) + return space.newtuple([W_StringObject(w_str._value)]) def repr__String(space, w_str): s = w_str._value Modified: pypy/dist/pypy/objspace/std/stringtype.py ============================================================================== --- pypy/dist/pypy/objspace/std/stringtype.py (original) +++ pypy/dist/pypy/objspace/std/stringtype.py Sat May 6 00:05:47 2006 @@ -48,7 +48,7 @@ return w_obj # XXX might be reworked when space.str() typechecks value = space.str_w(w_obj) w_obj = space.allocate_instance(W_StringObject, w_stringtype) - W_StringObject.__init__(w_obj, space, value) + W_StringObject.__init__(w_obj, value) return w_obj # ____________________________________________________________ Modified: pypy/dist/pypy/objspace/std/test/test_complexobject.py ============================================================================== --- pypy/dist/pypy/objspace/std/test/test_complexobject.py (original) +++ pypy/dist/pypy/objspace/std/test/test_complexobject.py Sat May 6 00:05:47 2006 @@ -12,7 +12,7 @@ def _test_instantiation(self): def _t_complex(r=0.0,i=0.0): - c = cobj.W_ComplexObject(self.space, r, i) + c = cobj.W_ComplexObject(r, i) assert c.real == float(r) and c.imag == float(i) pairs = ( (1, 1), @@ -51,8 +51,8 @@ assert cobj._powi((0.0,2.0),0) == (1.0,0.0) assert cobj._powi((0.0,0.0),2) == (0.0,0.0) assert cobj._powi((0.0,1.0),2) == (-1.0,0.0) - c = cobj.W_ComplexObject(self.space,0.0,1.0) - p = cobj.W_ComplexObject(self.space,2.0,0.0) + c = cobj.W_ComplexObject(0.0,1.0) + p = cobj.W_ComplexObject(2.0,0.0) r = cobj.pow__Complex_Complex_ANY(self.space,c,p,self.space.wrap(None)) assert r.realval == -1.0 assert r.imagval == 0.0 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 Sat May 6 00:05:47 2006 @@ -17,9 +17,9 @@ x = 10.0 y = 2.0 z = 13.0 - f1 = fobj.W_FloatObject(self.space, x) - f2 = fobj.W_FloatObject(self.space, y) - f3 = fobj.W_FloatObject(self.space, z) + f1 = fobj.W_FloatObject(x) + f2 = fobj.W_FloatObject(y) + f3 = fobj.W_FloatObject(z) assert self.space.w_TypeError == ( self._unwrap_nonimpl(fobj.pow__Float_Float_ANY, self.space, f1, f2, f3)) @@ -27,20 +27,20 @@ def test_pow_ffn(self): x = 10.0 y = 2.0 - f1 = fobj.W_FloatObject(self.space, x) - f2 = fobj.W_FloatObject(self.space, y) + f1 = fobj.W_FloatObject(x) + f2 = fobj.W_FloatObject(y) v = fobj.pow__Float_Float_ANY(self.space, f1, f2, self.space.w_None) assert v.floatval == x ** y - f1 = fobj.W_FloatObject(self.space, -1.23) - f2 = fobj.W_FloatObject(self.space, -4.56) + f1 = fobj.W_FloatObject(-1.23) + f2 = fobj.W_FloatObject(-4.56) assert self.space.w_ValueError == ( self._unwrap_nonimpl(fobj.pow__Float_Float_ANY, self.space, f1, f2, self.space.w_None)) x = -10 y = 2.0 - f1 = fobj.W_FloatObject(self.space, x) - f2 = fobj.W_FloatObject(self.space, y) + f1 = fobj.W_FloatObject(x) + f2 = fobj.W_FloatObject(y) v = fobj.pow__Float_Float_ANY(self.space, f1, f2, self.space.w_None) assert v.floatval == x**y Modified: pypy/dist/pypy/objspace/std/test/test_intobject.py ============================================================================== --- pypy/dist/pypy/objspace/std/test/test_intobject.py (original) +++ pypy/dist/pypy/objspace/std/test/test_intobject.py Sat May 6 00:05:47 2006 @@ -37,19 +37,19 @@ def test_repr(self): x = 1 - f1 = iobj.W_IntObject(self.space, x) + f1 = iobj.W_IntObject(x) result = iobj.repr__Int(self.space, f1) assert self.space.unwrap(result) == repr(x) def test_str(self): x = 12345 - f1 = iobj.W_IntObject(self.space, x) + f1 = iobj.W_IntObject(x) result = iobj.str__Int(self.space, f1) assert self.space.unwrap(result) == str(x) def test_hash(self): x = 42 - f1 = iobj.W_IntObject(self.space, x) + f1 = iobj.W_IntObject(x) result = iobj.hash__Int(self.space, f1) assert result.intval == hash(x) @@ -59,8 +59,8 @@ for x in (-10, -1, 0, 1, 2, 1000, sys.maxint): for y in (-sys.maxint-1, -11, -9, -2, 0, 1, 3, 1111, sys.maxint): for op in optab: - wx = iobj.W_IntObject(self.space, x) - wy = iobj.W_IntObject(self.space, y) + wx = iobj.W_IntObject(x) + wy = iobj.W_IntObject(y) res = getattr(operator, op)(x, y) method = getattr(iobj, '%s__Int_Int' % op) myres = method(self.space, wx, wy) @@ -69,64 +69,64 @@ def test_add(self): x = 1 y = 2 - f1 = iobj.W_IntObject(self.space, x) - f2 = iobj.W_IntObject(self.space, y) + f1 = iobj.W_IntObject(x) + f2 = iobj.W_IntObject(y) result = iobj.add__Int_Int(self.space, f1, f2) assert result.intval == x+y x = sys.maxint y = 1 - f1 = iobj.W_IntObject(self.space, x) - f2 = iobj.W_IntObject(self.space, y) + f1 = iobj.W_IntObject(x) + f2 = iobj.W_IntObject(y) assert self.space.w_OverflowError == ( self._unwrap_nonimpl(iobj.add__Int_Int, self.space, f1, f2)) def test_sub(self): x = 1 y = 2 - f1 = iobj.W_IntObject(self.space, x) - f2 = iobj.W_IntObject(self.space, y) + f1 = iobj.W_IntObject(x) + f2 = iobj.W_IntObject(y) result = iobj.sub__Int_Int(self.space, f1, f2) assert result.intval == x-y x = sys.maxint y = -1 - f1 = iobj.W_IntObject(self.space, x) - f2 = iobj.W_IntObject(self.space, y) + f1 = iobj.W_IntObject(x) + f2 = iobj.W_IntObject(y) assert self.space.w_OverflowError == ( self._unwrap_nonimpl(iobj.sub__Int_Int, self.space, f1, f2)) def test_mul(self): x = 2 y = 3 - f1 = iobj.W_IntObject(self.space, x) - f2 = iobj.W_IntObject(self.space, y) + f1 = iobj.W_IntObject(x) + f2 = iobj.W_IntObject(y) result = iobj.mul__Int_Int(self.space, f1, f2) assert result.intval == x*y x = -sys.maxint-1 y = -1 - f1 = iobj.W_IntObject(self.space, x) - f2 = iobj.W_IntObject(self.space, y) + f1 = iobj.W_IntObject(x) + f2 = iobj.W_IntObject(y) assert self.space.w_OverflowError == ( self._unwrap_nonimpl(iobj.mul__Int_Int, self.space, f1, f2)) def test_div(self): for i in range(10): res = i//3 - f1 = iobj.W_IntObject(self.space, i) - f2 = iobj.W_IntObject(self.space, 3) + f1 = iobj.W_IntObject(i) + f2 = iobj.W_IntObject(3) result = iobj.div__Int_Int(self.space, f1, f2) assert result.intval == res x = -sys.maxint-1 y = -1 - f1 = iobj.W_IntObject(self.space, x) - f2 = iobj.W_IntObject(self.space, y) + f1 = iobj.W_IntObject(x) + f2 = iobj.W_IntObject(y) assert self.space.w_OverflowError == ( self._unwrap_nonimpl(iobj.div__Int_Int, self.space, f1, f2)) def test_mod(self): x = 1 y = 2 - f1 = iobj.W_IntObject(self.space, x) - f2 = iobj.W_IntObject(self.space, y) + f1 = iobj.W_IntObject(x) + f2 = iobj.W_IntObject(y) v = iobj.mod__Int_Int(self.space, f1, f2) assert v.intval == x % y # not that mod cannot overflow @@ -134,15 +134,15 @@ def test_divmod(self): x = 1 y = 2 - f1 = iobj.W_IntObject(self.space, x) - f2 = iobj.W_IntObject(self.space, y) + f1 = iobj.W_IntObject(x) + f2 = iobj.W_IntObject(y) ret = iobj.divmod__Int_Int(self.space, f1, f2) v, w = self.space.unwrap(ret) assert (v, w) == divmod(x, y) x = -sys.maxint-1 y = -1 - f1 = iobj.W_IntObject(self.space, x) - f2 = iobj.W_IntObject(self.space, y) + f1 = iobj.W_IntObject(x) + f2 = iobj.W_IntObject(y) assert self.space.w_OverflowError == ( self._unwrap_nonimpl(iobj.divmod__Int_Int, self.space, f1, f2)) @@ -150,16 +150,16 @@ x = 10 y = 2 z = 13 - f1 = iobj.W_IntObject(self.space, x) - f2 = iobj.W_IntObject(self.space, y) - f3 = iobj.W_IntObject(self.space, z) + f1 = iobj.W_IntObject(x) + f2 = iobj.W_IntObject(y) + f3 = iobj.W_IntObject(z) v = iobj.pow__Int_Int_Int(self.space, f1, f2, f3) assert v.intval == pow(x, y, z) - f1, f2, f3 = [iobj.W_IntObject(self.space, i) for i in (10, -1, 42)] + f1, f2, f3 = [iobj.W_IntObject(i) for i in (10, -1, 42)] self.space.raises_w(self.space.w_TypeError, iobj.pow__Int_Int_Int, self.space, f1, f2, f3) - f1, f2, f3 = [iobj.W_IntObject(self.space, i) for i in (10, 5, 0)] + f1, f2, f3 = [iobj.W_IntObject(i) for i in (10, 5, 0)] self.space.raises_w(self.space.w_ValueError, iobj.pow__Int_Int_Int, self.space, f1, f2, f3) @@ -167,125 +167,125 @@ def test_pow_iin(self): x = 10 y = 2 - f1 = iobj.W_IntObject(self.space, x) - f2 = iobj.W_IntObject(self.space, y) + f1 = iobj.W_IntObject(x) + f2 = iobj.W_IntObject(y) v = iobj.pow__Int_Int_None(self.space, f1, f2, self.space.w_None) assert v.intval == x ** y - f1, f2 = [iobj.W_IntObject(self.space, i) for i in (10, 20)] + f1, f2 = [iobj.W_IntObject(i) for i in (10, 20)] assert self.space.w_OverflowError == ( self._unwrap_nonimpl(iobj.pow__Int_Int_None, self.space, f1, f2, self.space.w_None)) def test_neg(self): x = 42 - f1 = iobj.W_IntObject(self.space, x) + f1 = iobj.W_IntObject(x) v = iobj.neg__Int(self.space, f1) assert v.intval == -x x = -sys.maxint-1 - f1 = iobj.W_IntObject(self.space, x) + f1 = iobj.W_IntObject(x) assert self.space.w_OverflowError == ( self._unwrap_nonimpl(iobj.neg__Int, self.space, f1)) def test_pos(self): x = 42 - f1 = iobj.W_IntObject(self.space, x) + f1 = iobj.W_IntObject(x) v = iobj.pos__Int(self.space, f1) assert v.intval == +x x = -42 - f1 = iobj.W_IntObject(self.space, x) + f1 = iobj.W_IntObject(x) v = iobj.pos__Int(self.space, f1) assert v.intval == +x def test_abs(self): x = 42 - f1 = iobj.W_IntObject(self.space, x) + f1 = iobj.W_IntObject(x) v = iobj.abs__Int(self.space, f1) assert v.intval == abs(x) x = -42 - f1 = iobj.W_IntObject(self.space, x) + f1 = iobj.W_IntObject(x) v = iobj.abs__Int(self.space, f1) assert v.intval == abs(x) x = -sys.maxint-1 - f1 = iobj.W_IntObject(self.space, x) + f1 = iobj.W_IntObject(x) assert self.space.w_OverflowError == ( self._unwrap_nonimpl(iobj.abs__Int, self.space, f1)) def test_invert(self): x = 42 - f1 = iobj.W_IntObject(self.space, x) + f1 = iobj.W_IntObject(x) v = iobj.invert__Int(self.space, f1) assert v.intval == ~x def test_lshift(self): x = 12345678 y = 2 - f1 = iobj.W_IntObject(self.space, x) - f2 = iobj.W_IntObject(self.space, y) + f1 = iobj.W_IntObject(x) + f2 = iobj.W_IntObject(y) v = iobj.lshift__Int_Int(self.space, f1, f2) assert v.intval == x << y y = self._longshiftresult(x) - f1 = iobj.W_IntObject(self.space, x) - f2 = iobj.W_IntObject(self.space, y) + f1 = iobj.W_IntObject(x) + f2 = iobj.W_IntObject(y) assert self.space.w_OverflowError == ( self._unwrap_nonimpl(iobj.lshift__Int_Int, self.space, f1, f2)) def test_rshift(self): x = 12345678 y = 2 - f1 = iobj.W_IntObject(self.space, x) - f2 = iobj.W_IntObject(self.space, y) + f1 = iobj.W_IntObject(x) + f2 = iobj.W_IntObject(y) v = iobj.rshift__Int_Int(self.space, f1, f2) assert v.intval == x >> y def test_and(self): x = 12345678 y = 2 - f1 = iobj.W_IntObject(self.space, x) - f2 = iobj.W_IntObject(self.space, y) + f1 = iobj.W_IntObject(x) + f2 = iobj.W_IntObject(y) v = iobj.and__Int_Int(self.space, f1, f2) assert v.intval == x & y def test_xor(self): x = 12345678 y = 2 - f1 = iobj.W_IntObject(self.space, x) - f2 = iobj.W_IntObject(self.space, y) + f1 = iobj.W_IntObject(x) + f2 = iobj.W_IntObject(y) v = iobj.xor__Int_Int(self.space, f1, f2) assert v.intval == x ^ y def test_or(self): x = 12345678 y = 2 - f1 = iobj.W_IntObject(self.space, x) - f2 = iobj.W_IntObject(self.space, y) + f1 = iobj.W_IntObject(x) + f2 = iobj.W_IntObject(y) v = iobj.or__Int_Int(self.space, f1, f2) assert v.intval == x | y def test_int(self): - f1 = iobj.W_IntObject(self.space, 1) + f1 = iobj.W_IntObject(1) result = iobj.int__Int(self.space, f1) assert result == f1 ## def test_long(self): ## x = 1 -## f1 = iobj.W_IntObject(self.space, x) +## f1 = iobj.W_IntObject(x) ## result = iobj.int_long(self.space, f1) ## self.assertEquals(self.space.unwrap(result), long(x)) ## def test_float(self): ## x = 1 -## f1 = iobj.W_IntObject(self.space, x) +## f1 = iobj.W_IntObject(x) ## result = iobj.int_float(self.space, f1) ## self.assertEquals(self.space.unwrap(result), float(x)) def test_oct(self): x = 012345 - f1 = iobj.W_IntObject(self.space, x) + f1 = iobj.W_IntObject(x) result = iobj.oct__Int(self.space, f1) assert self.space.unwrap(result) == oct(x) def test_hex(self): x = 0x12345 - f1 = iobj.W_IntObject(self.space, x) + f1 = iobj.W_IntObject(x) result = iobj.hex__Int(self.space, f1) assert self.space.unwrap(result) == hex(x) Modified: pypy/dist/pypy/objspace/std/test/test_iterobject.py ============================================================================== --- pypy/dist/pypy/objspace/std/test/test_iterobject.py (original) +++ pypy/dist/pypy/objspace/std/test/test_iterobject.py Sat May 6 00:05:47 2006 @@ -18,7 +18,7 @@ def test_iter(self): w = self.space.wrap w_tuple = self.space.newtuple([w(5), w(3), w(99)]) - w_iter = W_SeqIterObject(self.space, w_tuple) + w_iter = W_SeqIterObject(w_tuple) self.body3(w_iter) def test_iter_builtin(self): @@ -29,7 +29,7 @@ def test_emptyiter(self): w_list = self.space.newlist([]) - w_iter = W_SeqIterObject(self.space, w_list) + w_iter = W_SeqIterObject(w_list) self.body0(w_iter) def test_emptyiter_builtin(self): 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 Sat May 6 00:05:47 2006 @@ -9,25 +9,25 @@ def test_is_true(self): w = self.space.wrap - w_list = W_ListObject(self.space, []) + w_list = W_ListObject([]) assert self.space.is_true(w_list) == False - w_list = W_ListObject(self.space, [w(5)]) + w_list = W_ListObject([w(5)]) assert self.space.is_true(w_list) == True - w_list = W_ListObject(self.space, [w(5), w(3)]) + w_list = W_ListObject([w(5), w(3)]) assert self.space.is_true(w_list) == True def test_len(self): w = self.space.wrap - w_list = W_ListObject(self.space, []) + w_list = W_ListObject([]) assert self.space.eq_w(self.space.len(w_list), w(0)) - w_list = W_ListObject(self.space, [w(5)]) + w_list = W_ListObject([w(5)]) assert self.space.eq_w(self.space.len(w_list), w(1)) - w_list = W_ListObject(self.space, [w(5), w(3), w(99)]*111) + w_list = W_ListObject([w(5), w(3), w(99)]*111) assert self.space.eq_w(self.space.len(w_list), w(333)) def test_getitem(self): w = self.space.wrap - w_list = W_ListObject(self.space, [w(5), w(3)]) + w_list = W_ListObject([w(5), w(3)]) assert self.space.eq_w(self.space.getitem(w_list, w(0)), w(5)) assert self.space.eq_w(self.space.getitem(w_list, w(1)), w(3)) assert self.space.eq_w(self.space.getitem(w_list, w(-2)), w(5)) @@ -42,7 +42,7 @@ 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)) + w_list = W_ListObject(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, @@ -65,7 +65,7 @@ def test_iter(self): w = self.space.wrap - w_list = W_ListObject(self.space, [w(5), w(3), w(99)]) + w_list = W_ListObject([w(5), w(3), w(99)]) w_iter = self.space.iter(w_list) assert self.space.eq_w(self.space.next(w_iter), w(5)) assert self.space.eq_w(self.space.next(w_iter), w(3)) @@ -75,7 +75,7 @@ def test_contains(self): w = self.space.wrap - w_list = W_ListObject(self.space, [w(5), w(3), w(99)]) + w_list = W_ListObject([w(5), w(3), w(99)]) assert self.space.eq_w(self.space.contains(w_list, w(5)), self.space.w_True) assert self.space.eq_w(self.space.contains(w_list, w(99)), @@ -90,7 +90,7 @@ def test1(testlist, start, stop, step, expected): w_slice = self.space.newslice(w(start), w(stop), w(step)) - w_list = W_ListObject(self.space, [w(i) for i in testlist]) + w_list = W_ListObject([w(i) for i in testlist]) w_result = self.space.getitem(w_list, w_slice) assert self.space.unwrap(w_result) == expected @@ -111,8 +111,8 @@ def test1(lhslist, start, stop, rhslist, expected): w_slice = self.space.newslice(w(start), w(stop), w(1)) - w_lhslist = W_ListObject(self.space, [w(i) for i in lhslist]) - w_rhslist = W_ListObject(self.space, [w(i) for i in rhslist]) + w_lhslist = W_ListObject([w(i) for i in lhslist]) + w_rhslist = W_ListObject([w(i) for i in rhslist]) self.space.setitem(w_lhslist, w_slice, w_rhslist) assert self.space.unwrap(w_lhslist) == expected @@ -126,14 +126,14 @@ def test_add(self): w = self.space.wrap - w_list0 = W_ListObject(self.space, []) - w_list1 = W_ListObject(self.space, [w(5), w(3), w(99)]) - w_list2 = W_ListObject(self.space, [w(-7)] * 111) + w_list0 = W_ListObject([]) + w_list1 = W_ListObject([w(5), w(3), w(99)]) + w_list2 = W_ListObject([w(-7)] * 111) assert self.space.eq_w(self.space.add(w_list1, w_list1), - W_ListObject(self.space, [w(5), w(3), w(99), + W_ListObject([w(5), w(3), w(99), w(5), w(3), w(99)])) assert self.space.eq_w(self.space.add(w_list1, w_list2), - W_ListObject(self.space, [w(5), w(3), w(99)] + + W_ListObject([w(5), w(3), w(99)] + [w(-7)] * 111)) assert self.space.eq_w(self.space.add(w_list1, w_list0), w_list1) assert self.space.eq_w(self.space.add(w_list0, w_list2), w_list2) @@ -143,8 +143,8 @@ w = self.space.wrap arg = w(2) n = 3 - w_lis = W_ListObject(self.space, [arg]) - w_lis3 = W_ListObject(self.space, [arg]*n) + w_lis = W_ListObject([arg]) + w_lis3 = W_ListObject([arg]*n) w_res = self.space.mul(w_lis, w(n)) assert self.space.eq_w(w_lis3, w_res) # commute @@ -153,9 +153,9 @@ def test_setitem(self): w = self.space.wrap - w_list = W_ListObject(self.space, [w(5), w(3)]) - w_exp1 = W_ListObject(self.space, [w(5), w(7)]) - w_exp2 = W_ListObject(self.space, [w(8), w(7)]) + w_list = W_ListObject([w(5), w(3)]) + w_exp1 = W_ListObject([w(5), w(7)]) + w_exp2 = W_ListObject([w(8), w(7)]) self.space.setitem(w_list, w(1), w(7)) assert self.space.eq_w(w_exp1, w_list) self.space.setitem(w_list, w(-2), w(8)) @@ -168,7 +168,7 @@ def test_random_setitem_delitem(self): w = self.space.wrap s = range(39) - w_list = W_ListObject(self.space, map(w, s)) + w_list = W_ListObject(map(w, s)) expected = list(s) keys = range(-len(s)-5, len(s)+5) choices = keys + [None]*12 @@ -184,7 +184,7 @@ for key in keys: if random.random() < 0.15: random.shuffle(s) - w_list = W_ListObject(self.space, map(w, s)) + w_list = W_ListObject(map(w, s)) expected = list(s) try: value = expected[key] @@ -220,10 +220,10 @@ def test_eq(self): w = self.space.wrap - w_list0 = W_ListObject(self.space, []) - w_list1 = W_ListObject(self.space, [w(5), w(3), w(99)]) - w_list2 = W_ListObject(self.space, [w(5), w(3), w(99)]) - w_list3 = W_ListObject(self.space, [w(5), w(3), w(99), w(-1)]) + w_list0 = W_ListObject([]) + w_list1 = W_ListObject([w(5), w(3), w(99)]) + w_list2 = W_ListObject([w(5), w(3), w(99)]) + w_list3 = W_ListObject([w(5), w(3), w(99), w(-1)]) assert self.space.eq_w(self.space.eq(w_list0, w_list1), self.space.w_False) @@ -238,10 +238,10 @@ def test_ne(self): w = self.space.wrap - w_list0 = W_ListObject(self.space, []) - w_list1 = W_ListObject(self.space, [w(5), w(3), w(99)]) - w_list2 = W_ListObject(self.space, [w(5), w(3), w(99)]) - w_list3 = W_ListObject(self.space, [w(5), w(3), w(99), w(-1)]) + w_list0 = W_ListObject([]) + w_list1 = W_ListObject([w(5), w(3), w(99)]) + w_list2 = W_ListObject([w(5), w(3), w(99)]) + w_list3 = W_ListObject([w(5), w(3), w(99), w(-1)]) assert self.space.eq_w(self.space.ne(w_list0, w_list1), self.space.w_True) @@ -256,11 +256,11 @@ def test_lt(self): w = self.space.wrap - w_list0 = W_ListObject(self.space, []) - w_list1 = W_ListObject(self.space, [w(5), w(3), w(99)]) - w_list2 = W_ListObject(self.space, [w(5), w(3), w(99)]) - w_list3 = W_ListObject(self.space, [w(5), w(3), w(99), w(-1)]) - w_list4 = W_ListObject(self.space, [w(5), w(3), w(9), w(-1)]) + w_list0 = W_ListObject([]) + w_list1 = W_ListObject([w(5), w(3), w(99)]) + w_list2 = W_ListObject([w(5), w(3), w(99)]) + w_list3 = W_ListObject([w(5), w(3), w(99), w(-1)]) + w_list4 = W_ListObject([w(5), w(3), w(9), w(-1)]) assert self.space.eq_w(self.space.lt(w_list0, w_list1), self.space.w_True) @@ -278,11 +278,11 @@ def test_ge(self): w = self.space.wrap - w_list0 = W_ListObject(self.space, []) - w_list1 = W_ListObject(self.space, [w(5), w(3), w(99)]) - w_list2 = W_ListObject(self.space, [w(5), w(3), w(99)]) - w_list3 = W_ListObject(self.space, [w(5), w(3), w(99), w(-1)]) - w_list4 = W_ListObject(self.space, [w(5), w(3), w(9), w(-1)]) + w_list0 = W_ListObject([]) + w_list1 = W_ListObject([w(5), w(3), w(99)]) + w_list2 = W_ListObject([w(5), w(3), w(99)]) + w_list3 = W_ListObject([w(5), w(3), w(99), w(-1)]) + w_list4 = W_ListObject([w(5), w(3), w(9), w(-1)]) assert self.space.eq_w(self.space.ge(w_list0, w_list1), self.space.w_False) @@ -300,11 +300,11 @@ def test_gt(self): w = self.space.wrap - w_list0 = W_ListObject(self.space, []) - w_list1 = W_ListObject(self.space, [w(5), w(3), w(99)]) - w_list2 = W_ListObject(self.space, [w(5), w(3), w(99)]) - w_list3 = W_ListObject(self.space, [w(5), w(3), w(99), w(-1)]) - w_list4 = W_ListObject(self.space, [w(5), w(3), w(9), w(-1)]) + w_list0 = W_ListObject([]) + w_list1 = W_ListObject([w(5), w(3), w(99)]) + w_list2 = W_ListObject([w(5), w(3), w(99)]) + w_list3 = W_ListObject([w(5), w(3), w(99), w(-1)]) + w_list4 = W_ListObject([w(5), w(3), w(9), w(-1)]) assert self.space.eq_w(self.space.gt(w_list0, w_list1), self.space.w_False) @@ -322,11 +322,11 @@ def test_le(self): w = self.space.wrap - w_list0 = W_ListObject(self.space, []) - w_list1 = W_ListObject(self.space, [w(5), w(3), w(99)]) - w_list2 = W_ListObject(self.space, [w(5), w(3), w(99)]) - w_list3 = W_ListObject(self.space, [w(5), w(3), w(99), w(-1)]) - w_list4 = W_ListObject(self.space, [w(5), w(3), w(9), w(-1)]) + w_list0 = W_ListObject([]) + w_list1 = W_ListObject([w(5), w(3), w(99)]) + w_list2 = W_ListObject([w(5), w(3), w(99)]) + w_list3 = W_ListObject([w(5), w(3), w(99), w(-1)]) + w_list4 = W_ListObject([w(5), w(3), w(9), w(-1)]) assert self.space.eq_w(self.space.le(w_list0, w_list1), self.space.w_True) Modified: pypy/dist/pypy/objspace/std/test/test_longobject.py ============================================================================== --- pypy/dist/pypy/objspace/std/test/test_longobject.py (original) +++ pypy/dist/pypy/objspace/std/test/test_longobject.py Sat May 6 00:05:47 2006 @@ -23,8 +23,8 @@ y = 123858582373821923936744221L for i in [-1, 1]: for j in [-1, 1]: - f1 = lobj.W_LongObject(self.space, *lobj.args_from_long(x * i)) - f2 = lobj.W_LongObject(self.space, *lobj.args_from_long(y * j)) + f1 = lobj.W_LongObject(*lobj.args_from_long(x * i)) + f2 = lobj.W_LongObject(*lobj.args_from_long(y * j)) result = lobj.add__Long_Long(self.space, f1, f2) assert result.longval() == x * i + y * j @@ -33,20 +33,20 @@ y = 88961284756491823819191823L for i in [-1, 1]: for j in [-1, 1]: - f1 = lobj.W_LongObject(self.space, *lobj.args_from_long(x * i)) - f2 = lobj.W_LongObject(self.space, *lobj.args_from_long(y * j)) + f1 = lobj.W_LongObject(*lobj.args_from_long(x * i)) + f2 = lobj.W_LongObject(*lobj.args_from_long(y * j)) result = lobj.sub__Long_Long(self.space, f1, f2) assert result.longval() == x * i - y * j def test_subzz(self): - w_l0 = lobj.W_LongObject(self.space, [0]) + w_l0 = lobj.W_LongObject([0]) assert self.space.sub(w_l0, w_l0).longval() == 0 def test_mul(self): x = -1238585838347L y = 585839391919233L - f1 = lobj.W_LongObject(self.space, *lobj.args_from_long(x)) - f2 = lobj.W_LongObject(self.space, *lobj.args_from_long(y)) + f1 = lobj.W_LongObject(*lobj.args_from_long(x)) + f2 = lobj.W_LongObject(*lobj.args_from_long(y)) result = lobj.mul__Long_Long(self.space, f1, f2) assert result.longval() == x * y # also test a * a, it has special code @@ -57,7 +57,7 @@ # signs are not handled in the helpers! x = 1238585838347L y = 3 - f1 = lobj.W_LongObject(self.space, *lobj.args_from_long(x)) + f1 = lobj.W_LongObject(*lobj.args_from_long(x)) f2 = y remainder = lobj._inplace_divrem1(f1, f1, f2) assert (f1.longval(), remainder) == divmod(x, y) @@ -66,7 +66,7 @@ # signs are not handled in the helpers! x = 1238585838347L y = 3 - f1 = lobj.W_LongObject(self.space, *lobj.args_from_long(x)) + f1 = lobj.W_LongObject(*lobj.args_from_long(x)) f2 = y div, rem = lobj._divrem1(f1, f2) assert (div.longval(), rem) == divmod(x, y) @@ -75,7 +75,7 @@ x = 1238585838347L y = 3 z = 42 - f1 = lobj.W_LongObject(self.space, *lobj.args_from_long(x)) + f1 = lobj.W_LongObject(*lobj.args_from_long(x)) f2 = y f3 = z prod = lobj._muladd1(f1, f2, f3) @@ -87,8 +87,8 @@ y = long(randint(0, 1 << 30)) y <<= 30 y += randint(0, 1 << 30) - f1 = lobj.W_LongObject(self.space, *lobj.args_from_long(x)) - f2 = lobj.W_LongObject(self.space, *lobj.args_from_long(y)) + f1 = lobj.W_LongObject(*lobj.args_from_long(x)) + f2 = lobj.W_LongObject(*lobj.args_from_long(y)) div, rem = lobj._x_divrem(f1, f2) assert div.longval(), rem.longval() == divmod(x, y) @@ -101,18 +101,18 @@ for sx, sy in (1, 1), (1, -1), (-1, -1), (-1, 1): sx *= x sy *= y - f1 = lobj.W_LongObject(self.space, *lobj.args_from_long(sx)) - f2 = lobj.W_LongObject(self.space, *lobj.args_from_long(sy)) + f1 = lobj.W_LongObject(*lobj.args_from_long(sx)) + f2 = lobj.W_LongObject(*lobj.args_from_long(sy)) div, rem = lobj._x_divrem(f1, f2) assert div.longval(), rem.longval() == divmod(sx, sy) def test__AsDouble(self): x = 12345678901234567890L ** 10 - f1 = lobj.W_LongObject(self.space, *lobj.args_from_long(x)) + f1 = lobj.W_LongObject(*lobj.args_from_long(x)) d = lobj._AsDouble(f1) assert d == float(x) x = x ** 100 - f1 = lobj.W_LongObject(self.space, *lobj.args_from_long(x)) + f1 = lobj.W_LongObject(*lobj.args_from_long(x)) assert raises(OverflowError, lobj._AsDouble, f1) def test__FromDouble(self): @@ -129,15 +129,15 @@ # testing Karatsuba stuff def test__v_iadd(self): - f1 = lobj.W_LongObject(self.space, [lobj.MASK] * 10, 1) - f2 = lobj.W_LongObject(self.space, [1], 1) + f1 = lobj.W_LongObject([lobj.MASK] * 10, 1) + f2 = lobj.W_LongObject([1], 1) carry = lobj._v_iadd(f1.digits, 1, len(f1.digits)-1, f2.digits, 1) assert carry == 1 assert f1.longval() == lobj.MASK def test__v_isub(self): - f1 = lobj.W_LongObject(self.space, [lobj.MASK] + [0] * 9 + [1], 1) - f2 = lobj.W_LongObject(self.space, [1], 1) + f1 = lobj.W_LongObject([lobj.MASK] + [0] * 9 + [1], 1) + f2 = lobj.W_LongObject([1], 1) borrow = lobj._v_isub(f1.digits, 1, len(f1.digits)-1, f2.digits, 1) assert borrow == 0 assert f1.longval() == (1 << lobj.SHIFT) ** 10 - 1 @@ -146,32 +146,32 @@ split = 5 diglo = [0] * split dighi = [lobj.MASK] * split - f1 = lobj.W_LongObject(self.space, diglo + dighi, 1) + f1 = lobj.W_LongObject(diglo + dighi, 1) hi, lo = lobj._kmul_split(f1, split) assert lo.digits == [0] assert hi.digits == dighi def test__k_mul(self): digs= lobj.KARATSUBA_CUTOFF * 5 - f1 = lobj.W_LongObject(self.space, [lobj.MASK] * digs, 1) - f2 = lobj._x_add(f1,lobj.W_LongObject(self.space, [1], 1)) + f1 = lobj.W_LongObject([lobj.MASK] * digs, 1) + f2 = lobj._x_add(f1,lobj.W_LongObject([1], 1)) ret = lobj._k_mul(f1, f2) assert ret.longval() == f1.longval() * f2.longval() def test__k_lopsided_mul(self): digs_a = lobj.KARATSUBA_CUTOFF + 3 digs_b = 3 * digs_a - f1 = lobj.W_LongObject(self.space, [lobj.MASK] * digs_a, 1) - f2 = lobj.W_LongObject(self.space, [lobj.MASK] * digs_b, 1) + f1 = lobj.W_LongObject([lobj.MASK] * digs_a, 1) + f2 = lobj.W_LongObject([lobj.MASK] * digs_b, 1) ret = lobj._k_lopsided_mul(f1, f2) assert ret.longval() == f1.longval() * f2.longval() def test_eq(self): x = 5858393919192332223L y = 585839391919233111223311112332L - f1 = lobj.W_LongObject(self.space, *lobj.args_from_long(x)) - f2 = lobj.W_LongObject(self.space, *lobj.args_from_long(-x)) - f3 = lobj.W_LongObject(self.space, *lobj.args_from_long(y)) + f1 = lobj.W_LongObject(*lobj.args_from_long(x)) + f2 = lobj.W_LongObject(*lobj.args_from_long(-x)) + f3 = lobj.W_LongObject(*lobj.args_from_long(y)) assert self.space.is_true(lobj.eq__Long_Long(self.space, f1, f1)) assert self.space.is_true(lobj.eq__Long_Long(self.space, f2, f2)) assert self.space.is_true(lobj.eq__Long_Long(self.space, f3, f3)) @@ -182,14 +182,14 @@ val = [0, 0x111111111111, 0x111111111112, 0x111111111112FFFF] for x in gen_signs(val): for y in gen_signs(val): - f1 = lobj.W_LongObject(self.space, *lobj.args_from_long(x)) - f2 = lobj.W_LongObject(self.space, *lobj.args_from_long(y)) + f1 = lobj.W_LongObject(*lobj.args_from_long(x)) + f2 = lobj.W_LongObject(*lobj.args_from_long(y)) assert (x < y) == self.space.is_true( lobj.lt__Long_Long(self.space, f1, f2)) def test_int_conversion(self): - f1 = lobj.W_LongObject(self.space, *lobj.args_from_long(12332)) - f2 = lobj.delegate_Int2Long(self.space.newint(12332)) + f1 = lobj.W_LongObject(*lobj.args_from_long(12332)) + f2 = lobj.delegate_Int2Long(self.space, self.space.newint(12332)) assert f2.longval() == f1.longval() assert lobj.int__Long(self.space, f2).intval == 12332 assert lobj.int_w__Long(self.space, f2) == 12332 @@ -203,9 +203,10 @@ def test_conversions(self): space = self.space for v in (0, 1, -1, sys.maxint, -sys.maxint-1): - assert lobj.W_LongObject(self.space, *lobj.args_from_long(v)).longval() == v + assert lobj.W_LongObject(*lobj.args_from_long(v)).longval() == v w_v = space.newint(v) - for w_lv in (lobj.long__Int(space, w_v), lobj.delegate_Int2Long(w_v)): + for w_lv in (lobj.long__Int(space, w_v), + lobj.delegate_Int2Long(self.space, w_v)): assert w_lv.longval() == v assert lobj.int_w__Long(space, w_lv) == v assert space.is_true(space.isinstance(lobj.int__Long(space, w_lv), space.w_int)) @@ -218,19 +219,19 @@ else: space.raises_w(space.w_ValueError, lobj.uint_w__Long, space, w_lv) - w_toobig_lv1 = lobj.W_LongObject(space, *lobj.args_from_long(sys.maxint+1)) + w_toobig_lv1 = lobj.W_LongObject(*lobj.args_from_long(sys.maxint+1)) assert w_toobig_lv1.longval() == sys.maxint+1 - w_toobig_lv2 = lobj.W_LongObject(space, *lobj.args_from_long(sys.maxint+2)) + w_toobig_lv2 = lobj.W_LongObject(*lobj.args_from_long(sys.maxint+2)) assert w_toobig_lv2.longval() == sys.maxint+2 - w_toobig_lv3 = lobj.W_LongObject(space, *lobj.args_from_long(-sys.maxint-2)) + w_toobig_lv3 = lobj.W_LongObject(*lobj.args_from_long(-sys.maxint-2)) assert w_toobig_lv3.longval() == -sys.maxint-2 for w_lv in (w_toobig_lv1, w_toobig_lv2, w_toobig_lv3): space.raises_w(space.w_OverflowError, lobj.int_w__Long, space, w_lv) assert space.is_true(space.isinstance(lobj.int__Long(space, w_lv), space.w_long)) - w_lmaxuint = lobj.W_LongObject(space, *lobj.args_from_long(2*sys.maxint+1)) - w_toobig_lv4 = lobj.W_LongObject(space, *lobj.args_from_long(2*sys.maxint+2)) + w_lmaxuint = lobj.W_LongObject(*lobj.args_from_long(2*sys.maxint+1)) + w_toobig_lv4 = lobj.W_LongObject(*lobj.args_from_long(2*sys.maxint+2)) u = lobj.uint_w__Long(space, w_lmaxuint) assert u == 2*sys.maxint+1 @@ -244,17 +245,17 @@ x = 10L y = 2L z = 13L - f1 = lobj.W_LongObject(self.space, *lobj.args_from_long(x)) - f2 = lobj.W_LongObject(self.space, *lobj.args_from_long(y)) - f3 = lobj.W_LongObject(self.space, *lobj.args_from_long(z)) + f1 = lobj.W_LongObject(*lobj.args_from_long(x)) + f2 = lobj.W_LongObject(*lobj.args_from_long(y)) + f3 = lobj.W_LongObject(*lobj.args_from_long(z)) v = lobj.pow__Long_Long_Long(self.space, f1, f2, f3) assert v.longval() == pow(x, y, z) - f1, f2, f3 = [lobj.W_LongObject(self.space, *lobj.args_from_long(i)) + f1, f2, f3 = [lobj.W_LongObject(*lobj.args_from_long(i)) for i in (10L, -1L, 42L)] self.space.raises_w(self.space.w_TypeError, lobj.pow__Long_Long_Long, self.space, f1, f2, f3) - f1, f2, f3 = [lobj.W_LongObject(self.space, *lobj.args_from_long(i)) + f1, f2, f3 = [lobj.W_LongObject(*lobj.args_from_long(i)) for i in (10L, 5L, 0L)] self.space.raises_w(self.space.w_ValueError, lobj.pow__Long_Long_Long, @@ -263,33 +264,33 @@ def test_pow_lln(self): x = 10L y = 2L - f1 = lobj.W_LongObject(self.space, *lobj.args_from_long(x)) - f2 = lobj.W_LongObject(self.space, *lobj.args_from_long(y)) + f1 = lobj.W_LongObject(*lobj.args_from_long(x)) + f2 = lobj.W_LongObject(*lobj.args_from_long(y)) v = lobj.pow__Long_Long_None(self.space, f1, f2, self.space.w_None) assert v.longval() == x ** y def test_normalize(self): - f1 = lobj.W_LongObject(self.space, [1, 0], 1) + f1 = lobj.W_LongObject([1, 0], 1) f1._normalize() assert len(f1.digits) == 1 - f0 = lobj.W_LongObject(self.space, [0], 0) + f0 = lobj.W_LongObject([0], 0) assert self.space.is_true( self.space.eq(lobj.sub__Long_Long(self.space, f1, f1), f0)) def test_invert(self): x = 3 ** 40 - f1 = lobj.W_LongObject(self.space, *lobj.args_from_long(x)) - f2 = lobj.W_LongObject(self.space, *lobj.args_from_long(-x)) + f1 = lobj.W_LongObject(*lobj.args_from_long(x)) + f2 = lobj.W_LongObject(*lobj.args_from_long(-x)) r1 = lobj.invert__Long(self.space, f1) r2 = lobj.invert__Long(self.space, f2) assert r1.longval() == -(x + 1) assert r2.longval() == -(-x + 1) def test_shift(self): - negative = lobj.W_LongObject(self.space, *lobj.args_from_long(-23)) - big = lobj.W_LongObject(self.space, *lobj.args_from_long(2L ** 100L)) + negative = lobj.W_LongObject(*lobj.args_from_long(-23)) + big = lobj.W_LongObject(*lobj.args_from_long(2L ** 100L)) for x in gen_signs([3L ** 30L, 5L ** 20L, 7 ** 300, 0L, 1L]): - f1 = lobj.W_LongObject(self.space, *lobj.args_from_long(x)) + f1 = lobj.W_LongObject(*lobj.args_from_long(x)) self.space.raises_w(self.space.w_ValueError, lobj.lshift__Long_Long, self.space, f1, negative) @@ -303,7 +304,7 @@ lobj.rshift__Long_Long, self.space, f1, big) for y in [0L, 1L, 32L, 2304L, 11233L, 3 ** 9]: - f2 = lobj.W_LongObject(self.space, *lobj.args_from_long(y)) + f2 = lobj.W_LongObject(*lobj.args_from_long(y)) res1 = lobj.lshift__Long_Long(self.space, f1, f2).longval() res2 = lobj.rshift__Long_Long(self.space, f1, f2).longval() assert res1 == x << y Modified: pypy/dist/pypy/objspace/std/test/test_multimethod.py ============================================================================== --- pypy/dist/pypy/objspace/std/test/test_multimethod.py (original) +++ pypy/dist/pypy/objspace/std/test/test_multimethod.py Sat May 6 00:05:47 2006 @@ -16,7 +16,7 @@ class W_StringObject(W_Root): pass -def delegate_b2i(w_x): +def delegate_b2i(space, w_x): assert isinstance(w_x, W_BoolObject) return W_IntObject() Modified: pypy/dist/pypy/objspace/std/test/test_sliceobject.py ============================================================================== --- pypy/dist/pypy/objspace/std/test/test_sliceobject.py (original) +++ pypy/dist/pypy/objspace/std/test/test_sliceobject.py Sat May 6 00:05:47 2006 @@ -8,18 +8,18 @@ w = space.wrap w_None = space.w_None w_slice = space.newslice(w_None, w_None, w_None) - assert w_slice.indices3(6) == (0, 6, 1) + assert w_slice.indices3(space, 6) == (0, 6, 1) w_slice = space.newslice(w(0), w(6), w(1)) - assert w_slice.indices3(6) == (0, 6, 1) + assert w_slice.indices3(space, 6) == (0, 6, 1) w_slice = space.newslice(w_None, w_None, w(-1)) - assert w_slice.indices3(6) == (5, -1, -1) + assert w_slice.indices3(space, 6) == (5, -1, -1) def test_indices_fail(self): space = self.space w = space.wrap w_None = space.w_None w_slice = space.newslice(w_None, w_None, w(0)) - self.space.raises_w(space.w_ValueError, w_slice.indices3, 10) + self.space.raises_w(space.w_ValueError, w_slice.indices3, space, 10) class AppTest_SliceObject: Modified: pypy/dist/pypy/objspace/std/test/test_tupleobject.py ============================================================================== --- pypy/dist/pypy/objspace/std/test/test_tupleobject.py (original) +++ pypy/dist/pypy/objspace/std/test/test_tupleobject.py Sat May 6 00:05:47 2006 @@ -9,25 +9,25 @@ def test_is_true(self): w = self.space.wrap - w_tuple = W_TupleObject(self.space, []) + w_tuple = W_TupleObject([]) assert self.space.is_true(w_tuple) == False - w_tuple = W_TupleObject(self.space, [w(5)]) + w_tuple = W_TupleObject([w(5)]) assert self.space.is_true(w_tuple) == True - w_tuple = W_TupleObject(self.space, [w(5), w(3)]) + w_tuple = W_TupleObject([w(5), w(3)]) assert self.space.is_true(w_tuple) == True def test_len(self): w = self.space.wrap - w_tuple = W_TupleObject(self.space, []) + w_tuple = W_TupleObject([]) assert self.space.eq_w(self.space.len(w_tuple), w(0)) - w_tuple = W_TupleObject(self.space, [w(5)]) + w_tuple = W_TupleObject([w(5)]) assert self.space.eq_w(self.space.len(w_tuple), w(1)) - w_tuple = W_TupleObject(self.space, [w(5), w(3), w(99)]*111) + w_tuple = W_TupleObject([w(5), w(3), w(99)]*111) assert self.space.eq_w(self.space.len(w_tuple), w(333)) def test_getitem(self): w = self.space.wrap - w_tuple = W_TupleObject(self.space, [w(5), w(3)]) + w_tuple = W_TupleObject([w(5), w(3)]) assert self.space.eq_w(self.space.getitem(w_tuple, w(0)), w(5)) assert self.space.eq_w(self.space.getitem(w_tuple, w(1)), w(3)) assert self.space.eq_w(self.space.getitem(w_tuple, w(-2)), w(5)) @@ -41,7 +41,7 @@ def test_iter(self): w = self.space.wrap - w_tuple = W_TupleObject(self.space, [w(5), w(3), w(99)]) + w_tuple = W_TupleObject([w(5), w(3), w(99)]) w_iter = self.space.iter(w_tuple) assert self.space.eq_w(self.space.next(w_iter), w(5)) assert self.space.eq_w(self.space.next(w_iter), w(3)) @@ -51,7 +51,7 @@ def test_contains(self): w = self.space.wrap - w_tuple = W_TupleObject(self.space, [w(5), w(3), w(99)]) + w_tuple = W_TupleObject([w(5), w(3), w(99)]) assert self.space.eq_w(self.space.contains(w_tuple, w(5)), self.space.w_True) assert self.space.eq_w(self.space.contains(w_tuple, w(99)), @@ -63,15 +63,14 @@ def test_add(self): w = self.space.wrap - w_tuple0 = W_TupleObject(self.space, []) - w_tuple1 = W_TupleObject(self.space, [w(5), w(3), w(99)]) - w_tuple2 = W_TupleObject(self.space, [w(-7)] * 111) + w_tuple0 = W_TupleObject([]) + w_tuple1 = W_TupleObject([w(5), w(3), w(99)]) + w_tuple2 = W_TupleObject([w(-7)] * 111) assert self.space.eq_w(self.space.add(w_tuple1, w_tuple1), - W_TupleObject(self.space, [w(5), w(3), w(99), + W_TupleObject([w(5), w(3), w(99), w(5), w(3), w(99)])) assert self.space.eq_w(self.space.add(w_tuple1, w_tuple2), - W_TupleObject(self.space, - [w(5), w(3), w(99)] + [w(-7)] * 111)) + W_TupleObject([w(5), w(3), w(99)] + [w(-7)] * 111)) assert self.space.eq_w(self.space.add(w_tuple1, w_tuple0), w_tuple1) assert self.space.eq_w(self.space.add(w_tuple0, w_tuple2), w_tuple2) @@ -80,8 +79,8 @@ w = self.space.wrap arg = w(2) n = 3 - w_tup = W_TupleObject(self.space, [arg]) - w_tup3 = W_TupleObject(self.space, [arg]*n) + w_tup = W_TupleObject([arg]) + w_tup3 = W_TupleObject([arg]*n) w_res = self.space.mul(w_tup, w(n)) assert self.space.eq_w(w_tup3, w_res) # commute @@ -93,7 +92,7 @@ def test1(testtuple, start, stop, step, expected): w_slice = self.space.newslice(w(start), w(stop), w(step)) - w_tuple = W_TupleObject(self.space, [w(i) for i in testtuple]) + w_tuple = W_TupleObject([w(i) for i in testtuple]) w_result = self.space.getitem(w_tuple, w_slice) assert self.space.unwrap(w_result) == expected @@ -112,10 +111,10 @@ def test_eq(self): w = self.space.wrap - w_tuple0 = W_TupleObject(self.space, []) - w_tuple1 = W_TupleObject(self.space, [w(5), w(3), w(99)]) - w_tuple2 = W_TupleObject(self.space, [w(5), w(3), w(99)]) - w_tuple3 = W_TupleObject(self.space, [w(5), w(3), w(99), w(-1)]) + w_tuple0 = W_TupleObject([]) + w_tuple1 = W_TupleObject([w(5), w(3), w(99)]) + w_tuple2 = W_TupleObject([w(5), w(3), w(99)]) + w_tuple3 = W_TupleObject([w(5), w(3), w(99), w(-1)]) assert self.space.eq_w(self.space.eq(w_tuple0, w_tuple1), self.space.w_False) @@ -130,10 +129,10 @@ def test_ne(self): w = self.space.wrap - w_tuple0 = W_TupleObject(self.space, []) - w_tuple1 = W_TupleObject(self.space, [w(5), w(3), w(99)]) - w_tuple2 = W_TupleObject(self.space, [w(5), w(3), w(99)]) - w_tuple3 = W_TupleObject(self.space, [w(5), w(3), w(99), w(-1)]) + w_tuple0 = W_TupleObject([]) + w_tuple1 = W_TupleObject([w(5), w(3), w(99)]) + w_tuple2 = W_TupleObject([w(5), w(3), w(99)]) + w_tuple3 = W_TupleObject([w(5), w(3), w(99), w(-1)]) assert self.space.eq_w(self.space.ne(w_tuple0, w_tuple1), self.space.w_True) @@ -148,11 +147,11 @@ def test_lt(self): w = self.space.wrap - w_tuple0 = W_TupleObject(self.space, []) - w_tuple1 = W_TupleObject(self.space, [w(5), w(3), w(99)]) - w_tuple2 = W_TupleObject(self.space, [w(5), w(3), w(99)]) - w_tuple3 = W_TupleObject(self.space, [w(5), w(3), w(99), w(-1)]) - w_tuple4 = W_TupleObject(self.space, [w(5), w(3), w(9), w(-1)]) + w_tuple0 = W_TupleObject([]) + w_tuple1 = W_TupleObject([w(5), w(3), w(99)]) + w_tuple2 = W_TupleObject([w(5), w(3), w(99)]) + w_tuple3 = W_TupleObject([w(5), w(3), w(99), w(-1)]) + w_tuple4 = W_TupleObject([w(5), w(3), w(9), w(-1)]) assert self.space.eq_w(self.space.lt(w_tuple0, w_tuple1), self.space.w_True) @@ -170,11 +169,11 @@ def test_ge(self): w = self.space.wrap - w_tuple0 = W_TupleObject(self.space, []) - w_tuple1 = W_TupleObject(self.space, [w(5), w(3), w(99)]) - w_tuple2 = W_TupleObject(self.space, [w(5), w(3), w(99)]) - w_tuple3 = W_TupleObject(self.space, [w(5), w(3), w(99), w(-1)]) - w_tuple4 = W_TupleObject(self.space, [w(5), w(3), w(9), w(-1)]) + w_tuple0 = W_TupleObject([]) + w_tuple1 = W_TupleObject([w(5), w(3), w(99)]) + w_tuple2 = W_TupleObject([w(5), w(3), w(99)]) + w_tuple3 = W_TupleObject([w(5), w(3), w(99), w(-1)]) + w_tuple4 = W_TupleObject([w(5), w(3), w(9), w(-1)]) assert self.space.eq_w(self.space.ge(w_tuple0, w_tuple1), self.space.w_False) @@ -192,11 +191,11 @@ def test_gt(self): w = self.space.wrap - w_tuple0 = W_TupleObject(self.space, []) - w_tuple1 = W_TupleObject(self.space, [w(5), w(3), w(99)]) - w_tuple2 = W_TupleObject(self.space, [w(5), w(3), w(99)]) - w_tuple3 = W_TupleObject(self.space, [w(5), w(3), w(99), w(-1)]) - w_tuple4 = W_TupleObject(self.space, [w(5), w(3), w(9), w(-1)]) + w_tuple0 = W_TupleObject([]) + w_tuple1 = W_TupleObject([w(5), w(3), w(99)]) + w_tuple2 = W_TupleObject([w(5), w(3), w(99)]) + w_tuple3 = W_TupleObject([w(5), w(3), w(99), w(-1)]) + w_tuple4 = W_TupleObject([w(5), w(3), w(9), w(-1)]) assert self.space.eq_w(self.space.gt(w_tuple0, w_tuple1), self.space.w_False) @@ -214,11 +213,11 @@ def test_le(self): w = self.space.wrap - w_tuple0 = W_TupleObject(self.space, []) - w_tuple1 = W_TupleObject(self.space, [w(5), w(3), w(99)]) - w_tuple2 = W_TupleObject(self.space, [w(5), w(3), w(99)]) - w_tuple3 = W_TupleObject(self.space, [w(5), w(3), w(99), w(-1)]) - w_tuple4 = W_TupleObject(self.space, [w(5), w(3), w(9), w(-1)]) + w_tuple0 = W_TupleObject([]) + w_tuple1 = W_TupleObject([w(5), w(3), w(99)]) + w_tuple2 = W_TupleObject([w(5), w(3), w(99)]) + w_tuple3 = W_TupleObject([w(5), w(3), w(99), w(-1)]) + w_tuple4 = W_TupleObject([w(5), w(3), w(9), w(-1)]) assert self.space.eq_w(self.space.le(w_tuple0, w_tuple1), self.space.w_True) Modified: pypy/dist/pypy/objspace/std/tupleobject.py ============================================================================== --- pypy/dist/pypy/objspace/std/tupleobject.py (original) +++ pypy/dist/pypy/objspace/std/tupleobject.py Sat May 6 00:05:47 2006 @@ -1,5 +1,5 @@ from pypy.objspace.std.objspace import * -from pypy.objspace.std.intobject import W_IntObject +from pypy.objspace.std.inttype import wrapint from pypy.rpython.rarithmetic import intmask from pypy.objspace.std.sliceobject import W_SliceObject from pypy.interpreter import gateway @@ -7,8 +7,7 @@ class W_TupleObject(W_Object): from pypy.objspace.std.tupletype import tuple_typedef as typedef - def __init__(w_self, space, wrappeditems): - W_Object.__init__(w_self, space) + def __init__(w_self, wrappeditems): w_self.wrappeditems = wrappeditems # a list of wrapped values def __repr__(w_self): @@ -16,8 +15,7 @@ reprlist = [repr(w_item) for w_item in w_self.wrappeditems] return "%s(%s)" % (w_self.__class__.__name__, ', '.join(reprlist)) - def unwrap(w_tuple): - space = w_tuple.space + def unwrap(w_tuple, space): items = [space.unwrap(w_item) for w_item in w_tuple.wrappeditems] # XXX generic mixed types unwrap return tuple(items) @@ -27,7 +25,7 @@ def len__Tuple(space, w_tuple): result = len(w_tuple.wrappeditems) - return W_IntObject(space, result) + return wrapint(result) def getitem__Tuple_ANY(space, w_tuple, w_index): items = w_tuple.wrappeditems @@ -41,13 +39,13 @@ def getitem__Tuple_Slice(space, w_tuple, w_slice): items = w_tuple.wrappeditems length = len(items) - start, stop, step, slicelength = w_slice.indices4(length) + start, stop, step, slicelength = w_slice.indices4(space, length) assert slicelength >= 0 subitems = [None] * slicelength for i in range(slicelength): subitems[i] = items[start] start += step - return W_TupleObject(space, subitems) + return W_TupleObject(subitems) def contains__Tuple_ANY(space, w_tuple, w_obj): for w_item in w_tuple.wrappeditems: @@ -57,12 +55,12 @@ def iter__Tuple(space, w_tuple): from pypy.objspace.std import iterobject - return iterobject.W_SeqIterObject(space, w_tuple) + return iterobject.W_SeqIterObject(w_tuple) def add__Tuple_Tuple(space, w_tuple1, w_tuple2): items1 = w_tuple1.wrappeditems items2 = w_tuple2.wrappeditems - return W_TupleObject(space, items1 + items2) + return W_TupleObject(items1 + items2) def mul_tuple_times(space, w_tuple, w_times): try: @@ -72,7 +70,7 @@ raise FailedToImplement raise items = w_tuple.wrappeditems - return W_TupleObject(space, items * times) + return W_TupleObject(items * times) def mul__Tuple_ANY(space, w_tuple, w_times): return mul_tuple_times(space, w_tuple, w_times) @@ -143,7 +141,7 @@ return space.wrap(intmask(x)) def getnewargs__Tuple(space, w_tuple): - return space.newtuple([W_TupleObject(space, w_tuple.wrappeditems)]) + return space.newtuple([W_TupleObject(w_tuple.wrappeditems)]) register_all(vars()) Modified: pypy/dist/pypy/objspace/std/tupletype.py ============================================================================== --- pypy/dist/pypy/objspace/std/tupletype.py (original) +++ pypy/dist/pypy/objspace/std/tupletype.py Sat May 6 00:05:47 2006 @@ -11,7 +11,7 @@ else: tuple_w = space.unpackiterable(w_sequence) w_obj = space.allocate_instance(W_TupleObject, w_tupletype) - W_TupleObject.__init__(w_obj, space, tuple_w) + W_TupleObject.__init__(w_obj, tuple_w) return w_obj # ____________________________________________________________ Modified: pypy/dist/pypy/objspace/std/typeobject.py ============================================================================== --- pypy/dist/pypy/objspace/std/typeobject.py (original) +++ pypy/dist/pypy/objspace/std/typeobject.py Sat May 6 00:05:47 2006 @@ -45,7 +45,7 @@ def __init__(w_self, space, name, bases_w, dict_w, overridetypedef=None): - W_Object.__init__(w_self, space) + w_self.space = space w_self.name = name w_self.bases_w = bases_w w_self.dict_w = dict_w @@ -297,7 +297,7 @@ dictspec = [] for key, w_value in w_self.dict_w.items(): dictspec.append((space.wrap(key), w_value)) - return W_DictProxyObject(space, space.newdict(dictspec)) + return W_DictProxyObject(space.newdict(dictspec)) def unwrap(w_self): if w_self.instancetypedef.fakedcpytype is not None: Modified: pypy/dist/pypy/objspace/std/unicodeobject.py ============================================================================== --- pypy/dist/pypy/objspace/std/unicodeobject.py (original) +++ pypy/dist/pypy/objspace/std/unicodeobject.py Sat May 6 00:05:47 2006 @@ -9,18 +9,14 @@ class W_UnicodeObject(W_Object): from pypy.objspace.std.unicodetype import unicode_typedef as typedef - def __init__(w_self, space, unicodechars): - W_Object.__init__(w_self, space) + def __init__(w_self, unicodechars): w_self._value = unicodechars - if len(unicodechars) == 0: - w_self.w_hash = space.wrap(0) - else: - w_self.w_hash = None + w_self.w_hash = None def __repr__(w_self): """ representation for debugging purposes """ return "%s(%r)" % (w_self.__class__.__name__, w_self._value) - def unwrap(w_self): + def unwrap(w_self, space): # For faked functions taking unicodearguments. # Remove when we no longer need faking. return u''.join(w_self._value) @@ -55,8 +51,7 @@ return ''.join(result) # string-to-unicode delegation -def delegate_String2Unicode(w_str): - space = w_str.space +def delegate_String2Unicode(space, w_str): w_uni = space.call_function(space.w_unicode, w_str) assert isinstance(w_uni, W_UnicodeObject) # help the annotator! return w_uni @@ -97,7 +92,7 @@ return space.wrap(ord(w_uni._value[0])) def getnewargs__Unicode(space, w_uni): - return space.newtuple([W_UnicodeObject(space, w_uni._value)]) + return space.newtuple([W_UnicodeObject(w_uni._value)]) def add__Unicode_Unicode(space, w_left, w_right): left = w_left._value @@ -109,7 +104,7 @@ result[i] = left[i] for i in range(rightlen): result[i + leftlen] = right[i] - return W_UnicodeObject(space, result) + return W_UnicodeObject(result) def add__String_Unicode(space, w_left, w_right): return space.add(space.call_function(space.w_unicode, w_left) , w_right) @@ -156,7 +151,7 @@ delim = w_self._value totlen = 0 if len(list) == 0: - return W_UnicodeObject(space, []) + return W_UnicodeObject([]) if (len(list) == 1 and space.is_w(space.type(list[0]), space.w_unicode)): return list[0] @@ -179,7 +174,7 @@ values_list[i] = item totlen += len(delim) * (len(values_list) - 1) if len(values_list) == 1: - return W_UnicodeObject(space, values_list[0]) + return W_UnicodeObject(values_list[0]) # Allocate result result = [u'\0'] * totlen first = values_list[0] @@ -196,7 +191,7 @@ for j in range(len(item)): result[offset + j] = item[j] offset += len(item) - return W_UnicodeObject(space, result) + return W_UnicodeObject(result) def hash__Unicode(space, w_uni): @@ -224,12 +219,12 @@ exc = space.call_function(space.w_IndexError, space.wrap("unicode index out of range")) raise OperationError(space.w_IndexError, exc) - return W_UnicodeObject(space, [uni[ival]]) + return W_UnicodeObject([uni[ival]]) def getitem__Unicode_Slice(space, w_uni, w_slice): uni = w_uni._value length = len(uni) - start, stop, step, sl = w_slice.indices4(length) + start, stop, step, sl = w_slice.indices4(space, length) if sl == 0: r = [] elif step == 1: @@ -237,18 +232,18 @@ r = uni[start:stop] else: r = [uni[start + i*step] for i in range(sl)] - return W_UnicodeObject(space, r) + return W_UnicodeObject(r) def mul__Unicode_ANY(space, w_uni, w_times): chars = w_uni._value charlen = len(chars) times = space.int_w(w_times) if times <= 0 or charlen == 0: - return W_UnicodeObject(space, []) + return W_UnicodeObject([]) if times == 1: return space.call_function(space.w_unicode, w_uni) if charlen == 1: - return W_UnicodeObject(space, [w_uni._value[0]] * times) + return W_UnicodeObject([w_uni._value[0]] * times) try: result = [u'\0'] * (charlen * times) @@ -258,7 +253,7 @@ offset = i * charlen for j in range(charlen): result[offset + j] = chars[j] - return W_UnicodeObject(space, result) + return W_UnicodeObject(result) def mul__ANY_Unicode(space, w_times, w_uni): return space.mul(w_uni, w_times) @@ -371,7 +366,7 @@ result = [u'\0'] * (rpos - lpos) for i in range(rpos - lpos): result[i] = u_self[lpos + i] - return W_UnicodeObject(space, result) + return W_UnicodeObject(result) def _strip_none(space, w_self, left, right): "internal function called by str_xstrip methods" @@ -391,7 +386,7 @@ result = [u'\0'] * (rpos - lpos) for i in range(rpos - lpos): result[i] = u_self[lpos + i] - return W_UnicodeObject(space, result) + return W_UnicodeObject(result) def unicode_strip__Unicode_None(space, w_self, w_chars): return _strip_none(space, w_self, 1, 1) @@ -420,12 +415,12 @@ def unicode_capitalize__Unicode(space, w_self): input = w_self._value if len(input) == 0: - return W_UnicodeObject(space, []) + return W_UnicodeObject([]) result = [u'\0'] * len(input) result[0] = unichr(unicodedb.toupper(ord(input[0]))) for i in range(1, len(input)): result[i] = unichr(unicodedb.tolower(ord(input[i]))) - return W_UnicodeObject(space, result) + return W_UnicodeObject(result) def unicode_title__Unicode(space, w_self): input = w_self._value @@ -441,21 +436,21 @@ else: result[i] = unichr(unicodedb.totitle(unichar)) previous_is_cased = unicodedb.iscased(unichar) - return W_UnicodeObject(space, result) + return W_UnicodeObject(result) def unicode_lower__Unicode(space, w_self): input = w_self._value result = [u'\0'] * len(input) for i in range(len(input)): result[i] = unichr(unicodedb.tolower(ord(input[i]))) - return W_UnicodeObject(space, result) + return W_UnicodeObject(result) def unicode_upper__Unicode(space, w_self): input = w_self._value result = [u'\0'] * len(input) for i in range(len(input)): result[i] = unichr(unicodedb.toupper(ord(input[i]))) - return W_UnicodeObject(space, result) + return W_UnicodeObject(result) def unicode_swapcase__Unicode(space, w_self): input = w_self._value @@ -468,7 +463,7 @@ result[i] = unichr(unicodedb.tolower(unichar)) else: result[i] = input[i] - return W_UnicodeObject(space, result) + return W_UnicodeObject(result) def _normalize_index(length, index): if index < 0: @@ -533,7 +528,7 @@ result = [fillchar] * width for i in range(len(self)): result[leftpad + i] = self[i] - return W_UnicodeObject(space, result) + return W_UnicodeObject(result) def unicode_ljust__Unicode_ANY_ANY(space, w_self, w_width, w_fillchar): self = w_self._value @@ -545,7 +540,7 @@ result = [fillchar] * width for i in range(len(self)): result[i] = self[i] - return W_UnicodeObject(space, result) + return W_UnicodeObject(result) def unicode_rjust__Unicode_ANY_ANY(space, w_self, w_width, w_fillchar): self = w_self._value @@ -557,13 +552,13 @@ result = [fillchar] * width for i in range(len(self)): result[padding + i] = self[i] - return W_UnicodeObject(space, result) + return W_UnicodeObject(result) def unicode_zfill__Unicode_ANY(space, w_self, w_width): self = w_self._value width = space.int_w(w_width) if len(self) == 0: - return W_UnicodeObject(space, [u'0'] * width) + return W_UnicodeObject([u'0'] * width) padding = width - len(self) if padding <= 0: return space.call_function(space.w_unicode, w_self) @@ -574,7 +569,7 @@ if self[0] in (u'+', u'-'): result[0] = self[0] result[padding] = u'0' - return W_UnicodeObject(space, result) + return W_UnicodeObject(result) def unicode_splitlines__Unicode_ANY(space, w_self, w_keepends): self = w_self._value @@ -593,18 +588,16 @@ if (self[pos] == u'\r' and pos + 1 < end and self[pos + 1] == u'\n'): # Count CRLF as one linebreak - lines.append(W_UnicodeObject(space, - self[start:pos + keepends * 2])) + lines.append(W_UnicodeObject(self[start:pos + keepends * 2])) pos += 1 else: - lines.append(W_UnicodeObject(space, - self[start:pos + keepends])) + lines.append(W_UnicodeObject(self[start:pos + keepends])) pos += 1 start = pos else: pos += 1 if not unicodedb.islinebreak(ord(self[end - 1])): - lines.append(W_UnicodeObject(space, self[start:])) + lines.append(W_UnicodeObject(self[start:])) return space.newlist(lines) def unicode_find__Unicode_Unicode_ANY_ANY(space, w_self, w_substr, w_start, w_end): @@ -678,7 +671,7 @@ else: break if inword == 1: - parts.append(W_UnicodeObject(space, self[start:index])) + parts.append(W_UnicodeObject(self[start:index])) maxsplit -= 1 # Eat whitespace for start in range(index + 1, end): @@ -687,7 +680,7 @@ else: return space.newlist(parts) - parts.append(W_UnicodeObject(space, self[start:])) + parts.append(W_UnicodeObject(self[start:])) return space.newlist(parts) def unicode_split__Unicode_Unicode_ANY(space, w_self, w_delim, w_maxsplit): @@ -707,10 +700,10 @@ index = _find(self, delim, start, end) if index < 0: break - parts.append(W_UnicodeObject(space, self[start:index])) + parts.append(W_UnicodeObject(self[start:index])) start = index + delim_len maxsplit -= 1 - parts.append(W_UnicodeObject(space, self[start:])) + parts.append(W_UnicodeObject(self[start:])) return space.newlist(parts) @@ -734,7 +727,7 @@ else: break if inword == 1: - parts.append(W_UnicodeObject(space, self[index+1:end])) + parts.append(W_UnicodeObject(self[index+1:end])) maxsplit -= 1 # Eat whitespace for end in range(index, start-1, -1): @@ -743,7 +736,7 @@ else: return space.newlist(parts) - parts.append(W_UnicodeObject(space, self[:end])) + parts.append(W_UnicodeObject(self[:end])) parts.reverse() return space.newlist(parts) @@ -764,10 +757,10 @@ index = _rfind(self, delim, 0, end) if index < 0: break - parts.append(W_UnicodeObject(space, self[index+delim_len:end])) + parts.append(W_UnicodeObject(self[index+delim_len:end])) end = index maxsplit -= 1 - parts.append(W_UnicodeObject(space, self[:end])) + parts.append(W_UnicodeObject(self[:end])) parts.reverse() return space.newlist(parts) @@ -775,18 +768,18 @@ if len(self) == 0: return [] if maxsplit == 0: - return [W_UnicodeObject(space, self)] + return [W_UnicodeObject(self)] index = 0 end = len(self) - parts = [W_UnicodeObject(space, [])] + parts = [W_UnicodeObject([])] maxsplit -= 1 while maxsplit != 0: if index >= end: break - parts.append(W_UnicodeObject(space, [self[index]])) + parts.append(W_UnicodeObject([self[index]])) index += 1 maxsplit -= 1 - parts.append(W_UnicodeObject(space, self[index:])) + parts.append(W_UnicodeObject(self[index:])) return parts def unicode_replace__Unicode_Unicode_Unicode_ANY(space, w_self, w_old, Modified: pypy/dist/pypy/objspace/std/unicodetype.py ============================================================================== --- pypy/dist/pypy/objspace/std/unicodetype.py (original) +++ pypy/dist/pypy/objspace/std/unicodetype.py Sat May 6 00:05:47 2006 @@ -92,7 +92,7 @@ # raising UnicodeDecodeError is messy, so "please crash for me" return unicode_from_object(space, w_str) codelist.append(unichr(code)) - return W_UnicodeObject(space, codelist) + return W_UnicodeObject(codelist) def descr__new__(space, w_unicodetype, w_string=None, w_encoding=None, w_errors=None): @@ -109,7 +109,7 @@ return w_obj w_value = w_obj elif space.is_w(w_obj, space.w_None): - w_value = W_UnicodeObject(space, []) + w_value = W_UnicodeObject([]) elif (space.is_w(w_encoding, space.w_None) and space.is_w(w_errors, space.w_None)): if space.is_true(space.isinstance(w_obj, space.w_str)): @@ -123,7 +123,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_UnicodeObject.__init__(w_newobj, space, w_value._value) + W_UnicodeObject.__init__(w_newobj, w_value._value) return w_newobj # ____________________________________________________________ From arigo at codespeak.net Sat May 6 00:07:20 2006 From: arigo at codespeak.net (arigo at codespeak.net) Date: Sat, 6 May 2006 00:07:20 +0200 (CEST) Subject: [pypy-svn] r26841 - pypy/dist/pypy/rpython/module Message-ID: <20060505220720.819B51006C@code0.codespeak.net> Author: arigo Date: Sat May 6 00:07:19 2006 New Revision: 26841 Modified: pypy/dist/pypy/rpython/module/ll_os.py pypy/dist/pypy/rpython/module/ll_os_path.py pypy/dist/pypy/rpython/module/support.py Log: Move some imports away to avoid importing the rtyper early during annotation. Modified: pypy/dist/pypy/rpython/module/ll_os.py ============================================================================== --- pypy/dist/pypy/rpython/module/ll_os.py (original) +++ pypy/dist/pypy/rpython/module/ll_os.py Sat May 6 00:07:19 2006 @@ -14,7 +14,6 @@ # and buffer preparation stuff is not useful. import os, errno -from pypy.rpython.lltypesystem.rstr import STR from pypy.rpython.lltypesystem.lltype import \ GcStruct, Signed, Array, Char, Ptr, malloc from pypy.rpython.module.support import to_rstr, from_rstr, ll_strcpy, _ll_strfill @@ -34,6 +33,7 @@ ll_read_into.suggested_primitive = True def ll_os_read(fd, count): + from pypy.rpython.lltypesystem.rstr import STR if count < 0: raise OSError(errno.EINVAL, None) buffer = malloc(STR, count) Modified: pypy/dist/pypy/rpython/module/ll_os_path.py ============================================================================== --- pypy/dist/pypy/rpython/module/ll_os_path.py (original) +++ pypy/dist/pypy/rpython/module/ll_os_path.py Sat May 6 00:07:19 2006 @@ -6,7 +6,6 @@ import os import stat -from pypy.rpython.lltypesystem.rstr import STR from pypy.rpython.module.support import to_rstr, from_rstr, ll_strcpy from pypy.rpython.module.ll_os import ll_os_stat Modified: pypy/dist/pypy/rpython/module/support.py ============================================================================== --- pypy/dist/pypy/rpython/module/support.py (original) +++ pypy/dist/pypy/rpython/module/support.py Sat May 6 00:07:19 2006 @@ -1,12 +1,12 @@ from pypy.rpython.lltypesystem import lltype from pypy.rpython import extfunctable -from pypy.rpython.lltypesystem.rstr import STR from pypy.rpython.lltypesystem.lltype import \ GcStruct, Signed, Array, Char, Ptr, malloc # utility conversion functions def to_rstr(s): + from pypy.rpython.lltypesystem.rstr import STR if s is None: return lltype.nullptr(STR) p = malloc(STR, len(s)) From arigo at codespeak.net Sat May 6 09:35:54 2006 From: arigo at codespeak.net (arigo at codespeak.net) Date: Sat, 6 May 2006 09:35:54 +0200 (CEST) Subject: [pypy-svn] r26842 - in pypy/dist/pypy/annotation: . test Message-ID: <20060506073554.264A21007E@code0.codespeak.net> Author: arigo Date: Sat May 6 09:35:51 2006 New Revision: 26842 Modified: pypy/dist/pypy/annotation/description.py pypy/dist/pypy/annotation/test/test_annrpython.py Log: Annotate classes that have __slots__. The slots are ignored, but they used to confuse the annotator because they show up in the class. Modified: pypy/dist/pypy/annotation/description.py ============================================================================== --- pypy/dist/pypy/annotation/description.py (original) +++ pypy/dist/pypy/annotation/description.py Sat May 6 09:35:51 2006 @@ -395,6 +395,10 @@ # that the py lib has its own AssertionError.__init__ which # is of type FunctionType. But bookkeeper.immutablevalue() # will do the right thing in s_get_value(). + + if type(value) is MemberDescriptorType: + # skip __slots__, showing up in the class as 'member' objects + continue self.classdict[name] = Constant(value) def getclassdef(self, key): @@ -759,3 +763,10 @@ def rowkey(self): return self.funcdesc + +# ____________________________________________________________ + +class Sample(object): + __slots__ = 'x' +MemberDescriptorType = type(Sample.x) +del Sample Modified: pypy/dist/pypy/annotation/test/test_annrpython.py ============================================================================== --- pypy/dist/pypy/annotation/test/test_annrpython.py (original) +++ pypy/dist/pypy/annotation/test/test_annrpython.py Sat May 6 09:35:51 2006 @@ -2060,6 +2060,20 @@ assert isinstance(s.items[1], annmodel.SomePBC) assert len(s.items[1].descriptions) == 1 + def test_slots(self): + # check that the annotator ignores slots instead of being + # confused by them showing up as 'member' objects in the class + class A(object): + __slots__ = ('a', 'b') + def f(x): + a = A() + a.b = x + return a.b + + a = self.RPythonAnnotator() + s = a.build_types(f, [int]) + assert s.knowntype == int + def g(n): return [0,1,2,n] From arigo at codespeak.net Sat May 6 09:54:02 2006 From: arigo at codespeak.net (arigo at codespeak.net) Date: Sat, 6 May 2006 09:54:02 +0200 (CEST) Subject: [pypy-svn] r26843 - in pypy/dist/pypy: annotation annotation/test rpython rpython/lltypesystem rpython/lltypesystem/test rpython/test Message-ID: <20060506075402.79B931007E@code0.codespeak.net> Author: arigo Date: Sat May 6 09:53:59 2006 New Revision: 26843 Modified: pypy/dist/pypy/annotation/builtin.py pypy/dist/pypy/annotation/description.py pypy/dist/pypy/annotation/test/test_annrpython.py pypy/dist/pypy/rpython/lltypesystem/rbuiltin.py pypy/dist/pypy/rpython/lltypesystem/rtagged.py pypy/dist/pypy/rpython/lltypesystem/test/test_rtagged.py pypy/dist/pypy/rpython/objectmodel.py pypy/dist/pypy/rpython/test/test_objectmodel.py Log: * fix for buggy __slots__ support * enhanced UnboxedValue to allow the value to also show up as an attribute, with a name chosen by the user Modified: pypy/dist/pypy/annotation/builtin.py ============================================================================== --- pypy/dist/pypy/annotation/builtin.py (original) +++ pypy/dist/pypy/annotation/builtin.py Sat May 6 09:53:59 2006 @@ -314,9 +314,6 @@ def robjmodel_hint(s, **kwds_s): return s -def robjmodel_getvalue_from_unboxed(s): - return SomeInteger() - def llmemory_cast_ptr_to_adr(s): return SomeAddress() @@ -373,8 +370,6 @@ BUILTIN_ANALYZERS[pypy.rpython.objectmodel.hlinvoke] = robjmodel_hlinvoke BUILTIN_ANALYZERS[pypy.rpython.objectmodel.keepalive_until_here] = robjmodel_keepalive_until_here BUILTIN_ANALYZERS[pypy.rpython.objectmodel.hint] = robjmodel_hint -BUILTIN_ANALYZERS[pypy.rpython.objectmodel.getvalue_from_unboxed] = \ - robjmodel_getvalue_from_unboxed BUILTIN_ANALYZERS[pypy.rpython.lltypesystem.llmemory.cast_ptr_to_adr] = llmemory_cast_ptr_to_adr BUILTIN_ANALYZERS[pypy.rpython.lltypesystem.llmemory.cast_adr_to_ptr] = llmemory_cast_adr_to_ptr BUILTIN_ANALYZERS[pypy.rpython.lltypesystem.llmemory.cast_adr_to_int] = llmemory_cast_adr_to_int Modified: pypy/dist/pypy/annotation/description.py ============================================================================== --- pypy/dist/pypy/annotation/description.py (original) +++ pypy/dist/pypy/annotation/description.py Sat May 6 09:53:59 2006 @@ -365,41 +365,41 @@ if base is not object: self.basedesc = bookkeeper.getdesc(base) + def add_source_attribute(self, name, value, mixin=False): + if isinstance(value, types.FunctionType): + # for debugging + if not hasattr(value, 'class_'): + value.class_ = self.pyobj # remember that this is really a method + if self.specialize: + # make a custom funcdesc that specializes on its first + # argument (i.e. 'self'). + from pypy.annotation.specialize import specialize_argtype + def argtype0(funcdesc, args_s): + return specialize_argtype(funcdesc, args_s, 0) + funcdesc = FunctionDesc(self.bookkeeper, value, + specializer=argtype0) + self.classdict[name] = funcdesc + return + if mixin: + # make a new copy of the FunctionDesc for this class, + # but don't specialize further for all subclasses + funcdesc = FunctionDesc(self.bookkeeper, value) + self.classdict[name] = funcdesc + return + # NB. if value is, say, AssertionError.__init__, then we + # should not use getdesc() on it. Never. The problem is + # that the py lib has its own AssertionError.__init__ which + # is of type FunctionType. But bookkeeper.immutablevalue() + # will do the right thing in s_get_value(). + + if type(value) is MemberDescriptorType: + # skip __slots__, showing up in the class as 'member' objects + return + self.classdict[name] = Constant(value) + def add_sources_for_class(self, cls, mixin=False): for name, value in cls.__dict__.items(): - ## -- useless? -- ignore some special attributes - ##if name.startswith('_') and not isinstance(value, types.FunctionType): - ## continue - if isinstance(value, types.FunctionType): - # for debugging - if not hasattr(value, 'class_'): - value.class_ = self.pyobj # remember that this is really a method - if self.specialize: - # make a custom funcdesc that specializes on its first - # argument (i.e. 'self'). - from pypy.annotation.specialize import specialize_argtype - def argtype0(funcdesc, args_s): - return specialize_argtype(funcdesc, args_s, 0) - funcdesc = FunctionDesc(self.bookkeeper, value, - specializer=argtype0) - self.classdict[name] = funcdesc - continue - if mixin: - # make a new copy of the FunctionDesc for this class, - # but don't specialize further for all subclasses - funcdesc = FunctionDesc(self.bookkeeper, value) - self.classdict[name] = funcdesc - continue - # NB. if value is, say, AssertionError.__init__, then we - # should not use getdesc() on it. Never. The problem is - # that the py lib has its own AssertionError.__init__ which - # is of type FunctionType. But bookkeeper.immutablevalue() - # will do the right thing in s_get_value(). - - if type(value) is MemberDescriptorType: - # skip __slots__, showing up in the class as 'member' objects - continue - self.classdict[name] = Constant(value) + self.add_source_attribute(name, value, mixin) def getclassdef(self, key): try: @@ -531,8 +531,9 @@ # there is a new attribute cls = self.pyobj if name in cls.__dict__: - self.classdict[name] = Constant(cls.__dict__[name]) - return self + self.add_source_attribute(name, cls.__dict__[name]) + if name in self.classdict: + return self return None def consider_call_site(bookkeeper, family, descs, args, s_result): Modified: pypy/dist/pypy/annotation/test/test_annrpython.py ============================================================================== --- pypy/dist/pypy/annotation/test/test_annrpython.py (original) +++ pypy/dist/pypy/annotation/test/test_annrpython.py Sat May 6 09:53:59 2006 @@ -2074,6 +2074,18 @@ s = a.build_types(f, [int]) assert s.knowntype == int + def test_unboxed_value(self): + class A(object): + pass + class C(A, objectmodel.UnboxedValue): + __slots__ = 'smallint' + def f(n): + return C(n).smallint + + a = self.RPythonAnnotator() + s = a.build_types(f, [int]) + assert s.knowntype == int + def g(n): return [0,1,2,n] Modified: pypy/dist/pypy/rpython/lltypesystem/rbuiltin.py ============================================================================== --- pypy/dist/pypy/rpython/lltypesystem/rbuiltin.py (original) +++ pypy/dist/pypy/rpython/lltypesystem/rbuiltin.py Sat May 6 09:53:59 2006 @@ -59,13 +59,8 @@ c = hop.inputconst(pyobj_repr, __import__) return hop.genop('simple_call', [c] + args_v, resulttype = pyobj_repr) -def rtype_getvalue_from_unboxed(hop): - from pypy.rpython.lltypesystem.rtagged import rtype_getvalue_from_unboxed - return rtype_getvalue_from_unboxed(hop) - BUILTIN_TYPER = {} BUILTIN_TYPER[objectmodel.instantiate] = rtype_instantiate -BUILTIN_TYPER[objectmodel.getvalue_from_unboxed] = rtype_getvalue_from_unboxed BUILTIN_TYPER[isinstance] = rtype_builtin_isinstance BUILTIN_TYPER[hasattr] = rtype_builtin_hasattr BUILTIN_TYPER[__import__] = rtype_builtin___import__ Modified: pypy/dist/pypy/rpython/lltypesystem/rtagged.py ============================================================================== --- pypy/dist/pypy/rpython/lltypesystem/rtagged.py (original) +++ pypy/dist/pypy/rpython/lltypesystem/rtagged.py Sat May 6 09:53:59 2006 @@ -16,9 +16,18 @@ def _setup_repr(self): InstanceRepr._setup_repr(self) - if len(self.allinstancefields) != 1: - raise TyperError("%r cannot have fields besides __class__: %r" % ( - self.classdef, self.allinstancefields.keys())) + flds = self.allinstancefields.keys() + flds.remove('__class__') + if self.is_parent: + if flds: + raise TyperError("%r is a base class of an UnboxedValue," + "so it cannot have fields: %r" % ( + self.classdef, flds)) + else: + if len(flds) != 1: + raise TyperError("%r must have exactly one field: %r" % ( + self.classdef, flds)) + self.specialfieldname = flds[0] def new_instance(self, llops, classcallhop=None): if self.is_parent: @@ -49,9 +58,13 @@ number = value.getvalue() return ll_int_to_unboxed(self.lowleveltype, number) - def getfield(self, vinst, attr, llops, force_cast=False): - if attr != '__class__': - raise MissingRTypeAttribute(attr) + def getvalue_from_unboxed(self, llops, vinst): + assert not self.is_parent + v2 = llops.genop('cast_ptr_to_int', [vinst], resulttype=lltype.Signed) + c_one = inputconst(lltype.Signed, 1) + return llops.genop('int_rshift', [v2, c_one], resulttype=lltype.Signed) + + def gettype_from_unboxed(self, llops, vinst): unboxedclass_repr = getclassrepr(self.rtyper, self.unboxedclassdef) cunboxedcls = inputconst(CLASSTYPE, unboxedclass_repr.getvtable()) if self.is_parent: @@ -61,12 +74,21 @@ else: return cunboxedcls + def getfield(self, vinst, attr, llops, force_cast=False): + if not self.is_parent and attr == self.specialfieldname: + return self.getvalue_from_unboxed(llops, vinst) + elif attr == '__class__': + return self.gettype_from_unboxed(llops, vinst) + else: + raise MissingRTypeAttribute(attr) + def rtype_type(self, hop): [vinst] = hop.inputargs(self) - return self.getfield(vinst, '__class__', hop.llops) + return self.gettype_from_unboxed(hop.llops, vinst) def rtype_setattr(self, hop): - raise TyperError("cannot set attributes on %r" % (self,)) + # only for UnboxedValue.__init__(), which is not actually called + hop.genop('UnboxedValue_setattr', []) def ll_str(self, i): if lltype.cast_ptr_to_int(i) & 1: @@ -116,12 +138,3 @@ return answer_if_unboxed else: return ll_issubclass_const(obj.typeptr, minid, maxid) - -def rtype_getvalue_from_unboxed(hop): - assert isinstance(hop.args_r[0], TaggedInstanceRepr) - assert not hop.args_r[0].is_parent - [v_instance] = hop.inputargs(hop.args_r[0]) - v2 = hop.genop('cast_ptr_to_int', [v_instance], resulttype = lltype.Signed) - c_one = hop.inputconst(lltype.Signed, 1) - return hop.genop('int_rshift', [v2, c_one], resulttype = lltype.Signed) - Modified: pypy/dist/pypy/rpython/lltypesystem/test/test_rtagged.py ============================================================================== --- pypy/dist/pypy/rpython/lltypesystem/test/test_rtagged.py (original) +++ pypy/dist/pypy/rpython/lltypesystem/test/test_rtagged.py Sat May 6 09:53:59 2006 @@ -15,15 +15,12 @@ return self.normalint + x + 2 class C(A, UnboxedValue): + __slots__ = 'smallint' def meth(self, x): - return self.getvalue() + x + 3 + return self.smallint + x + 3 # ____________________________________________________________ -def test_on_top_of_cpython(): - assert C(17).getvalue() == 17 - assert C(20).meth(10) == 33 - def test_instantiate(): def fn1(n): return C(n) @@ -31,6 +28,12 @@ value = lltype.cast_ptr_to_int(res) assert value == 42 * 2 + 1 # for now +def test_attribute(): + def fn1(n): + return C(n).smallint + res = interpret(fn1, [42]) + assert res == 42 + def test_getvalue(): def fn1(n): return C(n).getvalue() @@ -49,7 +52,7 @@ if isinstance(x, B): return 'B', x.normalint elif isinstance(x, C): - return 'C', x.getvalue() + return 'C', x.smallint else: return 'A', 0 @@ -68,7 +71,7 @@ x = c else: x = C(n) - return x.getvalue() + return x.smallint res = interpret(fn, [12]) assert res == 12 @@ -80,7 +83,7 @@ if x is None: return sys.maxint else: - return x.getvalue() + return x.smallint def fn(n): if n < 0: x = None Modified: pypy/dist/pypy/rpython/objectmodel.py ============================================================================== --- pypy/dist/pypy/rpython/objectmodel.py (original) +++ pypy/dist/pypy/rpython/objectmodel.py Sat May 6 09:53:59 2006 @@ -117,25 +117,28 @@ def __new__(cls, value): assert '__init__' not in cls.__dict__ # won't be called anyway + assert isinstance(cls.__slots__, str) or len(cls.__slots__) == 1 + return super(UnboxedValue, cls).__new__(cls) + + def __init__(self, value): + # this funtion is annotated but not included in the translated program int_as_pointer = value * 2 + 1 # XXX for now if -sys.maxint-1 <= int_as_pointer <= sys.maxint: - result = super(UnboxedValue, cls).__new__(cls) - result._value_ = value - return result + if isinstance(self.__slots__, str): + setattr(self, self.__slots__, value) + else: + setattr(self, self.__slots__[0], value) else: raise OverflowError("UnboxedValue: argument out of range") - def __init__(self, value): - pass - def __repr__(self): return '' % (self.getvalue(),) - def getvalue(self): - return getvalue_from_unboxed(self) - -def getvalue_from_unboxed(obj): - return obj._value_ # this function is special-cased by the annotator + def getvalue(self): # helper, equivalent to reading the custom field + if isinstance(self.__slots__, str): + return getattr(self, self.__slots__) + else: + return getattr(self, self.__slots__[0]) # ____________________________________________________________ Modified: pypy/dist/pypy/rpython/test/test_objectmodel.py ============================================================================== --- pypy/dist/pypy/rpython/test/test_objectmodel.py (original) +++ pypy/dist/pypy/rpython/test/test_objectmodel.py Sat May 6 09:53:59 2006 @@ -251,3 +251,18 @@ return d[2] res = interpret(g, [3]) assert res == 77 + +def test_unboxed_value(): + class Base(object): + pass + class C(Base, UnboxedValue): + __slots__ = 'smallint' + + assert C(17).smallint == 17 + assert C(17).getvalue() == 17 + + class A(UnboxedValue): + __slots__ = ['value'] + + assert A(12098).value == 12098 + assert A(12098).getvalue() == 12098 From arigo at codespeak.net Sat May 6 10:41:18 2006 From: arigo at codespeak.net (arigo at codespeak.net) Date: Sat, 6 May 2006 10:41:18 +0200 (CEST) Subject: [pypy-svn] r26845 - in pypy/dist/pypy/rpython/lltypesystem: . test Message-ID: <20060506084118.BCE251007E@code0.codespeak.net> Author: arigo Date: Sat May 6 10:41:17 2006 New Revision: 26845 Modified: pypy/dist/pypy/rpython/lltypesystem/rtagged.py pypy/dist/pypy/rpython/lltypesystem/test/test_rtagged.py Log: Fix and test for TaggedInstanceRepr.convert_const(). Modified: pypy/dist/pypy/rpython/lltypesystem/rtagged.py ============================================================================== --- pypy/dist/pypy/rpython/lltypesystem/rtagged.py (original) +++ pypy/dist/pypy/rpython/lltypesystem/rtagged.py Sat May 6 10:41:17 2006 @@ -5,6 +5,7 @@ from pypy.rpython.lltypesystem.rclass import MissingRTypeAttribute from pypy.rpython.lltypesystem.rclass import ll_issubclass_const from pypy.rpython.rmodel import TyperError, inputconst +from pypy.rpython.objectmodel import UnboxedValue class TaggedInstanceRepr(InstanceRepr): @@ -52,11 +53,11 @@ return v_instance, False # don't call __init__ def convert_const(self, value): - if value is None: - return self.null_instance() - else: + if isinstance(value, UnboxedValue): number = value.getvalue() return ll_int_to_unboxed(self.lowleveltype, number) + else: + return InstanceRepr.convert_const(self, value) def getvalue_from_unboxed(self, llops, vinst): assert not self.is_parent Modified: pypy/dist/pypy/rpython/lltypesystem/test/test_rtagged.py ============================================================================== --- pypy/dist/pypy/rpython/lltypesystem/test/test_rtagged.py (original) +++ pypy/dist/pypy/rpython/lltypesystem/test/test_rtagged.py Sat May 6 10:41:17 2006 @@ -66,17 +66,35 @@ def test_prebuilt(): c = C(111) - def fn(n): + b = B(939393) + + def makeint(n): if n < 0: x = c - else: + elif n > 0: x = C(n) - return x.smallint + else: + x = b + return x + + def fn(n): + x = makeint(n) + if isinstance(x, B): + return 'B', x.normalint + elif isinstance(x, C): + return 'C', x.smallint + else: + return 'A', 0 res = interpret(fn, [12]) - assert res == 12 + assert res.item0 == 'C' + assert res.item1 == 12 res = interpret(fn, [-1]) - assert res == 111 + assert res.item0 == 'C' + assert res.item1 == 111 + res = interpret(fn, [0]) + assert res.item0 == 'B' + assert res.item1 == 939393 def test_C_or_None(): def g(x): From arigo at codespeak.net Sat May 6 10:47:13 2006 From: arigo at codespeak.net (arigo at codespeak.net) Date: Sat, 6 May 2006 10:47:13 +0200 (CEST) Subject: [pypy-svn] r26846 - in pypy/dist/pypy/rpython: . lltypesystem Message-ID: <20060506084713.C37071007E@code0.codespeak.net> Author: arigo Date: Sat May 6 10:47:12 2006 New Revision: 26846 Modified: pypy/dist/pypy/rpython/lltypesystem/rtagged.py pypy/dist/pypy/rpython/rclass.py Log: More fixes for TaggedInstanceRepr.convert_const(). We need most of the parent's logic. Modified: pypy/dist/pypy/rpython/lltypesystem/rtagged.py ============================================================================== --- pypy/dist/pypy/rpython/lltypesystem/rtagged.py (original) +++ pypy/dist/pypy/rpython/lltypesystem/rtagged.py Sat May 6 10:47:12 2006 @@ -5,7 +5,6 @@ from pypy.rpython.lltypesystem.rclass import MissingRTypeAttribute from pypy.rpython.lltypesystem.rclass import ll_issubclass_const from pypy.rpython.rmodel import TyperError, inputconst -from pypy.rpython.objectmodel import UnboxedValue class TaggedInstanceRepr(InstanceRepr): @@ -52,12 +51,9 @@ resulttype = self.lowleveltype) return v_instance, False # don't call __init__ - def convert_const(self, value): - if isinstance(value, UnboxedValue): - number = value.getvalue() - return ll_int_to_unboxed(self.lowleveltype, number) - else: - return InstanceRepr.convert_const(self, value) + def convert_const_exact(self, value): + number = value.getvalue() + return ll_int_to_unboxed(self.lowleveltype, number) def getvalue_from_unboxed(self, llops, vinst): assert not self.is_parent Modified: pypy/dist/pypy/rpython/rclass.py ============================================================================== --- pypy/dist/pypy/rpython/rclass.py (original) +++ pypy/dist/pypy/rpython/rclass.py Sat May 6 10:47:12 2006 @@ -155,13 +155,16 @@ result = rinstance.convert_const(value) return self.upcast(result) # common case + return self.convert_const_exact(value) + + def convert_const_exact(self, value): try: return self.prebuiltinstances[id(value)][1] except KeyError: self.setup() result = self.create_instance() self.prebuiltinstances[id(value)] = value, result - self.initialize_prebuilt_instance(value, classdef, result) + self.initialize_prebuilt_instance(value, self.classdef, result) return result def rtype_type(self, hop): From arigo at codespeak.net Sat May 6 11:14:51 2006 From: arigo at codespeak.net (arigo at codespeak.net) Date: Sat, 6 May 2006 11:14:51 +0200 (CEST) Subject: [pypy-svn] r26849 - pypy/dist/pypy/doc/weekly Message-ID: <20060506091451.AB0F710076@code0.codespeak.net> Author: arigo Date: Sat May 6 11:14:50 2006 New Revision: 26849 Modified: pypy/dist/pypy/doc/weekly/log Log: This is not the worst place to record what I worked on recently. Modified: pypy/dist/pypy/doc/weekly/log ============================================================================== --- pypy/dist/pypy/doc/weekly/log (original) +++ pypy/dist/pypy/doc/weekly/log Sat May 6 11:14:50 2006 @@ -2,3 +2,28 @@ I wrote the fourth "This Week in PyPy". This 'log' file isn't really working, is it? + +2006-05-06 arigo + + Trying to revive this file, here are a few things of interest I worked + on recently: + + * rctypes. This is kind of complete. We can now translate RPython + programs using ctypes to C code that contains the corresponding + native calls, with reasonably good performance. + + * the CPyObjSpace aims at allowing PyPy's modules to be compiled to + regular CPython C extension modules. There are a few key features + missing but it is otherwise usable for mixed modules that don't + really use their app-level half. The entry point tool is + ``compilemodule.py``, currently in pypy.rpython.rctypes.tool. + + * translation support for tagged pointers: any instance of a class + inheriting from the mixin pypy.rpython.objectmodel.UnboxedValue + will be represented as a pointer whose bit pattern is an odd + integer. The restriction is that the class must only have one + read-only integer attribute. There is an experimental + pypy.objspace.std.smallintobject that uses this feature to + implement "small enough" app-level integers. (The app-level + cannot see the difference between "small enough" and reguar int + objects.) From bea at codespeak.net Sat May 6 11:52:02 2006 From: bea at codespeak.net (bea at codespeak.net) Date: Sat, 6 May 2006 11:52:02 +0200 (CEST) Subject: [pypy-svn] r26850 - pypy/extradoc/talk/agile2006 Message-ID: <20060506095202.638731007E@code0.codespeak.net> Author: bea Date: Sat May 6 11:52:01 2006 New Revision: 26850 Modified: pypy/extradoc/talk/agile2006/draftpaper_agile2006.txt Log: last changes - carl - can you look at my emails with formating feedback and then generate a new pdf - should be the last... Modified: pypy/extradoc/talk/agile2006/draftpaper_agile2006.txt ============================================================================== --- pypy/extradoc/talk/agile2006/draftpaper_agile2006.txt (original) +++ pypy/extradoc/talk/agile2006/draftpaper_agile2006.txt Sat May 6 11:52:01 2006 @@ -131,9 +131,8 @@ Programming and abstract interpretation techniques. The methodology objective aims at showcasing the "sprint-driven development method" being used by PyPy and you can view this paper as part of fulfilling the methodology objective. -See also a paper on the sprint method submitted to the XP 2006 conference titled -"Sprint-Driven Development: Agile methodologies in a Distributed Open Source -Project (PyPy)". +For more references on sprint-driven development, please see our paper for +the XP 2006 conference :raw-latex:`\cite{key-1}`. Strategy: +++++++++ @@ -208,7 +207,7 @@ The first funded year of the project ended with a review in Brussels in January 2006, hosted by the Commission, reviewing the 10 deliverables comprising the -work of the first year. All deliverables were accepted and based on +work of the first year. All deliverables were accepted; based on recommendations by the external reviewers. The consortium and the Commission is now restructuring the volume of the remaining the deliverables (although not changing the scope of the project). @@ -359,7 +358,7 @@ and BLOCKERS (if they are stuck and need help). This means that the group get overview and can track progress, albeit loosely. All individuals get an opportunity to voice their personal situation and the group jointly discuss potential blockers and how -to solve them. The fixed format help to keep focus and creates a rythm that makes it +to solve them. The fixed format help to keep focus and creates a rhythm that makes it easier for newcomers to get into the flow of the meeting. The third aspect is also the main challenge with the practice. In PyPy we rotate @@ -378,6 +377,7 @@ distributedly. They are also a lightweight way to syncronize activities, resolve blockers and to get an overview about who is currently doing what work."* + -- Carl Friedrich Bolz Influencing factors: agile practices in PyPy ============================================ @@ -448,7 +448,7 @@ sprint driven development. The sprint method, as well as key aspects of F/OSS supportive infrastructure -and practices was established within the project before PyPy received it?s +and practices was established within the project before PyPy received its EU-funding. Thus, in the proposal,we put much emphasis on the methodology in itself when designing the consortium level process. Examples of how this was done was that we created a methodology objective, specific deliverables @@ -485,7 +485,7 @@ Consortium structure -------------------- -Key requirements regarding organizational structures of an Framework Programme +Key requirements regarding organizational structures of a Framework Programme 6 EU-project are: - a consortium of partners performing the work described in the contract @@ -510,7 +510,7 @@ management team the strategy implemented was to delegate as much as possible of the responsibilities and decision-making to the core developers. -The strategy was to keep "conceptual integrity" :raw-latex:`\cite{key-1}` of +The strategy was to keep "conceptual integrity" :raw-latex:`\cite{key-2}` of the vision and the idea in the hands of the core developers. As Brooks stresses, a uniform system design is better than uncoordinated and independent design ideas. The core developers had a clear and agreed vision - but would @@ -559,8 +559,8 @@ physical meetings and discussions between the management team and the technical board etc. -Our funding have also resulted in the possibility to have a more unorthodox -documentation - the project have experimented in filming sprints to show the +Our funding have also resulted in the possibility to have a more unorthodox approach +to documentation - the project have experimented in filming sprints to show the development method as well as filming talks and discussion. Our film material is planned to be released before summer 2006. @@ -659,7 +659,7 @@ We believe so. The one clear dominating factor to make all this succeed is, as always, the people factor, the CRACK performers as Boehm and Turner calls them ("Collaborative, Representative, Authorized, Committed, Knowledgeable") -:raw-latex:`\cite{key-2}`. +:raw-latex:`\cite{key-3}`. The core developers of the PyPy project had the right mix of various skills in order to succeed in setting up a hybrid environment - enabling them to work @@ -709,7 +709,7 @@ what can be duplicated and tested in another project environment. This conclusion matches what Alistair Cockburn writes in his paper "Characterizing People as Non-Linear, First-Order Components in Software Development" -:raw-latex:`\cite{key-3}`: +:raw-latex:`\cite{key-4}`: *"The fundamental characteristics of "people" have a first-order effect on software development, not a lower-order effect."* @@ -751,14 +751,18 @@ .. raw:: latex \begin{thebibliography}{1} - \bibitem{key-1} Fredrick P. Brooks, Jr, "The mythical man-month, anniversary + + \bibitem{key-1} Beatrice D?ring, "Sprint-Driven Development: Agile methodologies + in a Distributed Open Source Project (PyPy)", XP 2006 + + \bibitem{key-2} Fredrick P. Brooks, Jr, "The mythical man-month, anniversary edition", Addison-Wesley, 1995 - \bibitem{key-2} Barry Boehm,Richard Turner, "Observations on Balancing + \bibitem{key-3} Barry Boehm,Richard Turner, "Observations on Balancing Discipline and Agility", (drawn from the book "Balancing Agility and Discipline: A Guide to the Perplexed", Addison Wesley, 2003) - \bibitem{key-3} Alistair Cockburn, "Characterizing People as Non-Linear, First-Order + \bibitem{key-4} Alistair Cockburn, "Characterizing People as Non-Linear, First-Order Components in Software Development", Presented at the 4th International Multi-Conference on Systems, Cybernetics and Informatics, Orlando, Florida, June, 2000, \texttt{http://alistair.cockburn.us/crystal/\\ From arigo at codespeak.net Sat May 6 12:09:33 2006 From: arigo at codespeak.net (arigo at codespeak.net) Date: Sat, 6 May 2006 12:09:33 +0200 (CEST) Subject: [pypy-svn] r26851 - pypy/dist/pypy/rpython/lltypesystem Message-ID: <20060506100933.662C210080@code0.codespeak.net> Author: arigo Date: Sat May 6 12:09:32 2006 New Revision: 26851 Modified: pypy/dist/pypy/rpython/lltypesystem/rtagged.py Log: Fix for a hard to reproduce bug. Modified: pypy/dist/pypy/rpython/lltypesystem/rtagged.py ============================================================================== --- pypy/dist/pypy/rpython/lltypesystem/rtagged.py (original) +++ pypy/dist/pypy/rpython/lltypesystem/rtagged.py Sat May 6 12:09:32 2006 @@ -52,6 +52,7 @@ return v_instance, False # don't call __init__ def convert_const_exact(self, value): + self.setup() number = value.getvalue() return ll_int_to_unboxed(self.lowleveltype, number) From arigo at codespeak.net Sat May 6 12:13:09 2006 From: arigo at codespeak.net (arigo at codespeak.net) Date: Sat, 6 May 2006 12:13:09 +0200 (CEST) Subject: [pypy-svn] r26852 - in pypy/dist/pypy/translator: . goal Message-ID: <20060506101309.A6CE910080@code0.codespeak.net> Author: arigo Date: Sat May 6 12:13:08 2006 New Revision: 26852 Modified: pypy/dist/pypy/translator/driver.py pypy/dist/pypy/translator/goal/translate.py pypy/dist/pypy/translator/interactive.py Log: Allow the interactive.Translation to compile stand-alone executables too. Modified: pypy/dist/pypy/translator/driver.py ============================================================================== --- pypy/dist/pypy/translator/driver.py (original) +++ pypy/dist/pypy/translator/driver.py Sat May 6 12:13:08 2006 @@ -42,7 +42,7 @@ class TranslationDriver(SimpleTaskEngine): def __init__(self, options=None, default_goal=None, disable=[], - exe_name = 'target-%(backend)s', extmod_name=None): + exe_name=None, extmod_name=None): SimpleTaskEngine.__init__(self) self.log = log @@ -155,6 +155,10 @@ annotator = translator.buildannotator(policy=policy) s = annotator.build_types(self.entry_point, self.inputtypes) self.sanity_check_annotation() + if self.standalone and s.knowntype != int: + raise Exception("stand-alone program entry point must return an " + "int (and not, e.g., None or always raise an " + "exception).") annotator.simplify() return s # @@ -267,14 +271,15 @@ task_source_c = taskdef(task_source_c, ['database_c'], "Generating c source") def create_exe(self): - import shutil - exename = mkexename(self.c_entryp) - newexename = self.exe_name % self.options.__dict__ - if '/' not in newexename and '\\' not in newexename: - newexename = './' + newexename - newexename = mkexename(newexename) - shutil.copy(exename, newexename) - self.c_entryp = newexename + if self.exe_name is not None: + import shutil + exename = mkexename(self.c_entryp) + newexename = self.exe_name % self.options.__dict__ + if '/' not in newexename and '\\' not in newexename: + newexename = './' + newexename + newexename = mkexename(newexename) + shutil.copy(exename, newexename) + self.c_entryp = newexename self.log.info("created: %s" % (self.c_entryp,)) def task_compile_c(self): # xxx messy @@ -346,7 +351,7 @@ def task_compile_llvm(self): gen = self.llvmgen if self.standalone: - exe_name = self.exe_name % self.options.__dict__ + exe_name = (self.exe_name or 'testing') % self.options.__dict__ self.c_entryp = gen.compile_llvm_source(exe_name=exe_name) self.create_exe() else: @@ -420,9 +425,6 @@ options = DEFAULT_OPTIONS driver = TranslationDriver(options, default_goal, disable) - if '__name__' in targetspec_dic: - driver.exe_name = targetspec_dic['__name__'] + '-%(backend)s' - target = targetspec_dic['target'] spec = target(driver, args) Modified: pypy/dist/pypy/translator/goal/translate.py ============================================================================== --- pypy/dist/pypy/translator/goal/translate.py (original) +++ pypy/dist/pypy/translator/goal/translate.py Sat May 6 12:13:08 2006 @@ -316,6 +316,9 @@ default_goal='compile') pdb_plus_show.expose({'drv': drv}) + if drv.exe_name is None and '__name__' in targetspec_dic: + drv.exe_name = targetspec_dic['__name__'] + '-%(backend)s' + goals = options.goals drv.proceed(goals) Modified: pypy/dist/pypy/translator/interactive.py ============================================================================== --- pypy/dist/pypy/translator/interactive.py (original) +++ pypy/dist/pypy/translator/interactive.py Sat May 6 12:13:08 2006 @@ -73,24 +73,31 @@ used_opts = dict.fromkeys(self.GOAL_USES_OPTS[goal], True) self.frozen_options.update(used_opts) - def ensure_setup(self, argtypes=None, policy=None): + def ensure_setup(self, argtypes=None, policy=None, standalone=False): if not self.driver_setup: - if argtypes is None: - argtypes = [] + if standalone: + assert argtypes is None + else: + if argtypes is None: + argtypes = [] self.driver.setup(self.entry_point, argtypes, policy, empty_translator=self.context) self.ann_argtypes = argtypes self.ann_policy = policy self.driver_setup = True else: # check consistency - if argtypes is not None and argtypes != self.ann_argtypes: + if standalone: + assert argtypes is None + assert self.ann_argtypes is None + elif argtypes is not None and argtypes != self.ann_argtypes: raise Exception("inconsistent argtype supplied") if policy is not None and policy != self.ann_policy: raise Exception("inconsistent annotation polish supplied") def update_options(self, argtypes, kwds): - if argtypes or kwds.get('policy'): - self.ensure_setup(argtypes, kwds.get('policy')) + if argtypes or kwds.get('policy') or kwds.get('standalone'): + self.ensure_setup(argtypes, kwds.get('policy'), + kwds.get('standalone')) for optname, value in kwds.iteritems(): if optname in self.frozen_options: if getattr(self.driver.options, optname) != value: From arigo at codespeak.net Sat May 6 12:13:58 2006 From: arigo at codespeak.net (arigo at codespeak.net) Date: Sat, 6 May 2006 12:13:58 +0200 (CEST) Subject: [pypy-svn] r26853 - in pypy/dist/pypy/translator/c: . test Message-ID: <20060506101358.A5DCC10080@code0.codespeak.net> Author: arigo Date: Sat May 6 12:13:57 2006 New Revision: 26853 Added: pypy/dist/pypy/translator/c/test/test_rtagged.py (contents, props changed) Modified: pypy/dist/pypy/translator/c/database.py Log: GenC support for prebuilt tagged pointers that are actually odd integers. Modified: pypy/dist/pypy/translator/c/database.py ============================================================================== --- pypy/dist/pypy/translator/c/database.py (original) +++ pypy/dist/pypy/translator/c/database.py Sat May 6 12:13:57 2006 @@ -168,6 +168,10 @@ return PrimitiveName[T](obj, self) elif isinstance(T, Ptr): if obj: # test if the ptr is non-NULL + if isinstance(obj._obj, int): + # special case for tagged odd-valued pointers + return '((%s) %d)' % (cdecl(self.gettype(T), ''), + obj._obj) node = self.getcontainernode(obj._obj) return node.ptrname else: Added: pypy/dist/pypy/translator/c/test/test_rtagged.py ============================================================================== --- (empty file) +++ pypy/dist/pypy/translator/c/test/test_rtagged.py Sat May 6 12:13:57 2006 @@ -0,0 +1,78 @@ +import sys, os +from pypy.rpython.objectmodel import UnboxedValue + + +class A(object): + def meth(self, x): + raise NotImplementedError + +class B(A): + def __init__(self, normalint): + self.normalint = normalint + def meth(self, x): + return self.normalint + x + 2 + +class C(A, UnboxedValue): + __slots__ = 'smallint' + def meth(self, x): + return self.smallint + x + 3 + +def makeint(n): + try: + return C(n) + except OverflowError: # 'n' out of range + return B(n) + +def makeint2(n): + if n < 0: + x = prebuilt_c + elif n > 0: + x = C(n) + else: + x = prebuilt_b + return x + +prebuilt_c = C(111) +prebuilt_b = B(939393) + +def entry_point(argv): + n = 100 + len(argv) + assert C(n).getvalue() == n + + x = makeint(42) + assert isinstance(x, C) + assert x.smallint == 42 + + x = makeint(sys.maxint) + assert isinstance(x, B) + assert x.normalint == sys.maxint + + x = makeint2(12) + assert x.meth(1000) == 1015 + + x = makeint2(-1) + assert x.meth(1000) == 1114 + + x = makeint2(0) + assert x.meth(1000) == 940395 + + os.write(1, "ALL OK\n") + return 0 + +# ____________________________________________________________ +# only with Boehm so far + +from pypy.translator.interactive import Translation +from pypy import conftest + +def test_tagged_boehm(): + t = Translation(entry_point, standalone=True, gc='boehm') + try: + exename = t.compile_c() + finally: + if conftest.option.view: + t.view() + g = os.popen(exename, 'r') + data = g.read() + g.close() + assert data.rstrip().endswith('ALL OK') From bea at codespeak.net Sat May 6 12:14:51 2006 From: bea at codespeak.net (bea at codespeak.net) Date: Sat, 6 May 2006 12:14:51 +0200 (CEST) Subject: [pypy-svn] r26854 - pypy/extradoc/talk/agile2006 Message-ID: <20060506101451.34AC110080@code0.codespeak.net> Author: bea Date: Sat May 6 12:14:49 2006 New Revision: 26854 Modified: pypy/extradoc/talk/agile2006/draftpaper_agile2006.txt Log: last spell check Modified: pypy/extradoc/talk/agile2006/draftpaper_agile2006.txt ============================================================================== --- pypy/extradoc/talk/agile2006/draftpaper_agile2006.txt (original) +++ pypy/extradoc/talk/agile2006/draftpaper_agile2006.txt Sat May 6 12:14:49 2006 @@ -241,7 +241,7 @@ The PyPy project inherited the focus on collaborative approaches and open communication climate. The strategy of using sprints, as a core technique, to kick-start the project as well as moving the sprints to different -locations had clear effects.It encouraged participation by meeting people locally. +locations had clear effects. It encouraged participation by meeting people locally. During the period of 2003-2004 6 sprints were arranged in various European cities. These sprints were hosted by universities and private individuals, participation was funded privately. The effect on the evolving community @@ -275,7 +275,7 @@ generated web pages that show the status of all tests as per the latest checked in test results. This together with a public issue-tracker covering bugs keeps the development group focused on the quality of the code when doing -continous integration. It greatly reduces the need +continuous integration. It greatly reduces the need to coordinate and delegate refactoring work - this is handled in a self-organized way. The main communication channels between developers involved in PyPy is to @@ -285,7 +285,7 @@ developer server for everyone to access. A very useful feature that really supports information and communication are the public email archives covering the key mailing lists - going back to the start of 2003. As a newcomer to the project -in the fall of 2003 these public and easily accessable mailing list archives +in the fall of 2003 these public and easily accessible mailing list archives was the primary means for me personally to get into the project. It provided answers to who had been key people in the process, what had been crucial topics, how had discussions and decisions been handled. It is also regularly being used with newcomers @@ -346,10 +346,10 @@ team focus-and-feel for the dispersed work style between sprints. There are three crucial aspects of this practice. The first one is that our experience as well as that of Canonical points to keeping the time for the meeting brief. The reason for -30 minutes limit is that it forces prioritization on what topics to choose. However +30 minutes limit is that it gives priority on what topics to choose. However complex your development situation is you should choose not more than 3 topics, topics that could be discussed and decided upon during these 30 minutes. Not having -this timelimit would create long and tiresome IRC meetings which would demotivate +this time limit would create long and tiresome IRC meetings which would affect motivation people and also create more confusion than results. The second aspect is that it has a fixed format in which the meeting starts with @@ -374,7 +374,7 @@ *"Sync-meetings are useful because they enable developers to discuss and clarify issues among themselves and to provide a common focus when working - distributedly. They are also a lightweight way to syncronize activities, + distributedly. They are also a lightweight way to synchronize activities, resolve blockers and to get an overview about who is currently doing what work."* -- Carl Friedrich Bolz @@ -514,7 +514,7 @@ the vision and the idea in the hands of the core developers. As Brooks stresses, a uniform system design is better than uncoordinated and independent design ideas. The core developers had a clear and agreed vision - but would -they be allowed to implement it within a fixed contract workstyle, with new +they be allowed to implement it within a fixed contract work style, with new partners involved that had not been involved in the process from the start? The core developers were organized into a technical board, responsible for planning and coordinating the development work between the partners, with the mandate to @@ -667,7 +667,7 @@ skills for making this possible was/are: - **Social:** The ability to communicate open and transparent, to mentor and - tutor dispersed as well as reinventing different collaborative workstyles of + tutor dispersed as well as reinventing different collaborative work styles of the sprint method, "manage" groups and community as well as consortium, and handle conflicts) @@ -684,7 +684,7 @@ seeking bets practices of other projects. - **Entrepreneurs:** To risk the community through pursuing the idea of - EU-funding in order to fullfill the ambitious vision, managing to not only + EU-funding in order to fulfill the ambitious vision, managing to not only create a consortium with innovative structures of cooperation but also to create new companies. @@ -718,7 +718,7 @@ get innovative regarding practices. Designing the project process based on the specific needs of the unique project environment you are facing. In the case of PyPy this means that we are exploring the methodology as we go along, adjusting -and finetuning the process as well as the software. +and fine tuning the process as well as the software. So, when drawing from these different skills within the community of developers, the people, in the PyPy project one possible conclusion would be @@ -735,7 +735,7 @@ the foundation for a hybrid project where agile practices and EU-funding can fit within a distributed Open Source context. -Acknowledgements +Acknowledgments ================ The author would like to thank the following people who have in various ways @@ -772,4 +772,3 @@ \end{thebibliography} - From cfbolz at codespeak.net Sat May 6 12:33:50 2006 From: cfbolz at codespeak.net (cfbolz at codespeak.net) Date: Sat, 6 May 2006 12:33:50 +0200 (CEST) Subject: [pypy-svn] r26855 - pypy/extradoc/talk/agile2006 Message-ID: <20060506103350.667CB1007F@code0.codespeak.net> Author: cfbolz Date: Sat May 6 12:33:43 2006 New Revision: 26855 Modified: pypy/extradoc/talk/agile2006/draftpaper_agile2006.pdf pypy/extradoc/talk/agile2006/draftpaper_agile2006.txt Log: regeneration of pdf + removal of colons in titles Modified: pypy/extradoc/talk/agile2006/draftpaper_agile2006.pdf ============================================================================== Binary files. No diff available. Modified: pypy/extradoc/talk/agile2006/draftpaper_agile2006.txt ============================================================================== --- pypy/extradoc/talk/agile2006/draftpaper_agile2006.txt (original) +++ pypy/extradoc/talk/agile2006/draftpaper_agile2006.txt Sat May 6 12:33:43 2006 @@ -32,8 +32,8 @@ -Introduction: -============= +Introduction +============ This paper presents the story and the experiences gathered so far in the PyPy project. The challenge has been to integrate such diverse perspectives as agile @@ -104,8 +104,8 @@ Project context --------------- -Objectives: -+++++++++++ +Objectives +++++++++++ Due to the dual nature of the project even such a thing as objectives can get complicated. If you, as a potential PyPy user, would visit out main developer @@ -134,8 +134,8 @@ For more references on sprint-driven development, please see our paper for the XP 2006 conference :raw-latex:`\cite{key-1}`. -Strategy: -+++++++++ +Strategy +++++++++ The strategy of the project is to leverage the community of PyPy and Python through an open and transparent communication and working style. The challenge has @@ -173,8 +173,8 @@ mentioned above almost all of them (10 people) are involved in some sense in the partner companies and organizations of the PyPy consortium. -History: -++++++++ +History ++++++++ The ideas behind PyPy started via discussions on European mailing-lists in the Python community late 2002 by people who had been active in the Python @@ -377,7 +377,7 @@ distributedly. They are also a lightweight way to synchronize activities, resolve blockers and to get an overview about who is currently doing what work."* - -- Carl Friedrich Bolz + :raw-latex:`--` Carl Friedrich Bolz Influencing factors: agile practices in PyPy ============================================ From cfbolz at codespeak.net Sat May 6 12:52:30 2006 From: cfbolz at codespeak.net (cfbolz at codespeak.net) Date: Sat, 6 May 2006 12:52:30 +0200 (CEST) Subject: [pypy-svn] r26856 - pypy/extradoc/talk/agile2006 Message-ID: <20060506105230.50ADE1007B@code0.codespeak.net> Author: cfbolz Date: Sat May 6 12:52:24 2006 New Revision: 26856 Added: pypy/extradoc/talk/agile2006/draftpaper_agile2006.dvi (contents, props changed) pypy/extradoc/talk/agile2006/draftpaper_agile2006.tex Log: check in tex and dvi file Added: pypy/extradoc/talk/agile2006/draftpaper_agile2006.dvi ============================================================================== Binary file. No diff available. Added: pypy/extradoc/talk/agile2006/draftpaper_agile2006.tex ============================================================================== --- (empty file) +++ pypy/extradoc/talk/agile2006/draftpaper_agile2006.tex Sat May 6 12:52:24 2006 @@ -0,0 +1,912 @@ +\documentclass[twocolumn,10pt,a4paper,english]{article} +\usepackage{latex8} +\usepackage{babel} +\usepackage{ae} +\usepackage{aeguill} +\usepackage{shortvrb} +\usepackage[latin1]{inputenc} +\usepackage{tabularx} +\usepackage{longtable} +\setlength{\extrarowheight}{2pt} +\usepackage{amsmath} +\usepackage{graphicx} +\usepackage{color} +\usepackage{multirow} +\usepackage{ifthen} +\usepackage[colorlinks=false,linkcolor=black,urlcolor=black]{hyperref} +\usepackage[DIV12]{typearea} +%% generator Docutils: http://docutils.sourceforge.net/ +\newlength{\admonitionwidth} +\setlength{\admonitionwidth}{0.9\textwidth} +\newlength{\docinfowidth} +\setlength{\docinfowidth}{0.9\textwidth} +\newlength{\locallinewidth} +\newcommand{\optionlistlabel}[1]{\bf #1 \hfill} +\newenvironment{optionlist}[1] +{\begin{list}{} + {\setlength{\labelwidth}{#1} + \setlength{\rightmargin}{1cm} + \setlength{\leftmargin}{\rightmargin} + \addtolength{\leftmargin}{\labelwidth} + \addtolength{\leftmargin}{\labelsep} + \renewcommand{\makelabel}{\optionlistlabel}} +}{\end{list}} +\newlength{\lineblockindentation} +\setlength{\lineblockindentation}{2.5em} +\newenvironment{lineblock}[1] +{\begin{list}{} + {\setlength{\partopsep}{\parskip} + \addtolength{\partopsep}{\baselineskip} + \topsep0pt\itemsep0.15\baselineskip\parsep0pt + \leftmargin#1} + \raggedright} +{\end{list}} +% begin: floats for footnotes tweaking. +\setlength{\floatsep}{0.5em} +\setlength{\textfloatsep}{\fill} +\addtolength{\textfloatsep}{3em} +\renewcommand{\textfraction}{0.5} +\renewcommand{\topfraction}{0.5} +\renewcommand{\bottomfraction}{0.5} +\setcounter{totalnumber}{50} +\setcounter{topnumber}{50} +\setcounter{bottomnumber}{50} +% end floats for footnotes +% some commands, that could be overwritten in the style file. +\newcommand{\rubric}[1]{\subsection*{~\hfill {\it #1} \hfill ~}} +\newcommand{\titlereference}[1]{\textsl{#1}} +% end of "some commands" +\title{Trouble in Paradise: the Open Source project PyPy, EU-funding and Agile practices} +\input{paper.sty} +\hypersetup{ +pdftitle={Trouble in Paradise: the Open Source project PyPy, EU-funding and Agile practices} +} +\raggedbottom +\begin{document} +\maketitle + + +\setlength{\locallinewidth}{\linewidth} +% sectnum +\begin{abstract} +PyPy is an Open Source project, partly funded by the European Union, employing +agile techniques evolved within the Python Community such as ``sprint-driven +development''.The project started as a grass-root F/OSS effort in late 2002 and +received EU-funding from December 2004 until November 2006. In this paper we +will present the various influencing factors that creates the hybrid project +process that is PyPy. These influencing factors are the F/OSS Python Community +(climate of the community from which PyPy grew from), agile practices (such as +the Python community evolved technique of ``sprinting'') and the EU funding +practices (resource tracking and reporting) impacting the project. These +influencing factors laid the foundation for the custom-made project process +that makes this unique hybrid project work. The main factor for driving this +process is the skills of the team of core developers instigating the project. +PyPy, with its open and transparent communication and collaborative work style, +is again a proof that the best agile practice is the people factor. +\end{abstract} + +%___________________________________________________________________________ + +\hypertarget{introduction}{} +\section{Introduction} + +This paper presents the story and the experiences gathered so far in the PyPy +project. The challenge has been to integrate such diverse perspectives as agile +practices being used in a distributed development style in an +Open Source project that is partly funded by the European Union. + +The PyPy project started as a grass-root effort among core developers in the +Python language community, aiming at building a Python implementation purely +built in Python. It was a language implementation project that was purely +driven from a non-profit perspective which rapidly increased in complexity when +the Open Source project applied for EU-funding. + +Today the project has over 4 years of intense activity as an Open Source +community (F/OSS, Free Open Source Software) effort and have completed a +successful first year of the EU-funded effort. In order to understand how the +PyPy project manages to strike a balance between being an F/OSS community, +while also having the core work of the project being funded by the European +Union (with all the structure and process requirements that entails) we need to +look at the influencing factors of the project process. + +The influencing factors of the PyPy project process are: +\begin{itemize} +\item {} +The F/OSS/Python community factor. Different Open Source communities have +different ``flavors'' regarding culture, communication climate, structure, +decision-process etc. PyPy was born out of the Python Community and shares +some of its characteristics which have had a huge influence on the project +process so far. Aspects such as distributed/dispersed development and the +supporting practices and infrastructure in place to quality assure software +development in a collaborated manner are part of this important influencing +factor. + +\item {} +The Agile factor. Almost a subset of the F/OSS/Python community factor - +agile practices that have been in use since the inception of the project, that +in fact have been the main drivers of the project are very much inspired by +other projects in the Python community. A key aspect of this influencing +factor is the Python version of ``sprinting''. We will present this ``agile'' +practice, explain and trace its origins within the Python community and +identify which of the main agile practices inspired the Python world to go +``sprinting'' - a key technique today not only for the PyPy project but also +for all main Python projects. We will also touch on aspects such as Test +Driven Development and explain how these are implemented in PyPy. + +\item {} +The EU factor. PyPy is the first F/OSS community that organized themselves +into an EU-project, receiving EU-funding. It has had a huge impact on the +project, and it is important to identify how EU project and process +requirements can be ``weaved'' into an Agile F/OSS project - a challenge +indeed. The EU-funding has been and still is an enormous opportunity; the +project would not have had the rapid progress and impact it is now having +without the funding. It is also very important to note that without striking +the right balance between the three main influencing factors (F/OSS, agile +and EU-funding) this factor might also prove to be a ``show stopper'', something +that might influence the PyPy community negatively. This is a constant +challenge - we explain here how we created our process and added a +``consortium-level'' structure to the F/OSS community and the steps we took in +order to mitigate this risk. + +\end{itemize} + +Our conclusion so far in the project is that we believe that the practice of +sprint-driven development, as being used in the PyPy project, makes Agile and +Distributed/dispersed work styles more possible to combine. We also believe it +is a very useful practice for creating value and ensuring quality in projects +with hybrid cultures and methodologies. It is our aim to start to show-case +this with experiences from the first funded year of PyPy. We also feel that our +experiences as a unique hybrid project would be of interest to other +communities such as the agile community and we hope that this paper will +encourage cross-community interaction and communication. + + +%___________________________________________________________________________ + +\hypertarget{project-context}{} +\subsection{Project context} + + +%___________________________________________________________________________ + +\hypertarget{objectives}{} +\subsubsection{Objectives} + +Due to the dual nature of the project even such a thing as objectives can get +complicated. If you, as a potential PyPy user, would visit out main developer +server, Codespeak, you would find the following statement: + +``The PyPy project aims at producing a flexible and fast Python implementation. +The guiding idea is to translate a Python-level description of the Python +language itself to lower level languages. Rumors have it that the secret goal +is being faster-than-C which is nonsense, isn't it? more...'' + +Codespeak housed the F/OSS project since its inception and it has been a +driving strategy to continue a look-and-feel of a purely F/OSS project in order +to not confuse developers interested in just that - PyPy as a Python +implementation. + +Digging a bit deeper you can find documentation which states the objectives of +the EU-funded part of the project. The EU project?s title is ``PyPy'' which is an +``acronym'' for ``Researching a Highly Flexible and Modular Language Platform and +Implementing it by Leveraging the Open Source Python Language and Community''. +The EU-project has three objectives: one technical, one research-oriented and +one methodology-oriented objective. In short PyPy is about building an +optimized compiler and interpreter purely in Python, applying Aspect Oriented +Programming and abstract interpretation techniques. The methodology objective +aims at showcasing the ``sprint-driven development method'' being used by PyPy +and you can view this paper as part of fulfilling the methodology objective. +For more references on sprint-driven development, please see our paper for +the XP 2006 conference \cite{key-1}. + + +%___________________________________________________________________________ + +\hypertarget{strategy}{} +\subsubsection{Strategy} + +The strategy of the project is to leverage the community of PyPy and Python +through an open and transparent communication and working style. The challenge has +been to implement this strategy, not only in the F/OSS community part of the +project, but also in the partially funded consortium structure of the project. + +The F/OSS part of PyPy has no budget tied to it and no formal organizational +structure. There are no resources tied to it other than the volunteers +participating in the development process. These are the core developers and +architects behind PyPy but also people from all over the world, driven by a +combination of professional need and personal interest in Python language +implementations such as PyPy and choosing to contribute to PyPy. There is also +a large group of students on PHD levels participating and contributing, using +their areas of interest in PyPy as thesis materials. + +It is difficult to estimate the amount of people involved in PyPy but we +estimate that 300-500 people actively follow the progress of the project - +this might mean reading emails, IRC logs and documentation in some cases, asking +questions and sending bug reports in others. There are around 50 people who +have commit-rights to the source code. The core group of developers consists of +around 10 people. + +The EU part of the project is organized through a consortium which consists of +8 partners: DFKI (Germany), Ab Strakt (Sweden), Logilab (France), merlinux GmbH +(Germany), tismerysoft GmbH (Germany), Change Maker (Sweden) , Impara GmbH +(Germany) and Heinrich Heine Universit?t D?sseldorf (Germany) and 4 physical +person partners: Laura Creighton (Sweden), Richard Emslie (UK), Eric Van Riet +Paap (Netherlands) , Niklaus Haldiman (Switzerland). + +The project effort of work for the 2 years of funding consists of 14 +work-packages and in total 58 deliverables which are high-level functional and +non-functional requirements that were formulated in a proposal and form the +``Description of Work'' in the contract with the European Commission. The funding +received for this effort is 1.3 million euro. Of the core group of developers +mentioned above almost all of them (10 people) are involved in some sense in +the partner companies and organizations of the PyPy consortium. + + +%___________________________________________________________________________ + +\hypertarget{history}{} +\subsubsection{History} + +The ideas behind PyPy started via discussions on European mailing-lists in the +Python community late 2002 by people who had been active in the Python +community for some time; core developers interested in language implementation. +They based the discussions and ideas partly on their experiences with +developing and driving some well-known projects in the Python community. They +met up in February 2003 at a ``sprint'', a one week working meeting,to draft +their ideas and to start PyPy as an Open Source project. The sprint facilities +as well as travel, accommodation and time was financed by all participants +privately. + +Mid 2003 the idea of trying to get EU-funding for the project was born. It +became clear that the project had an arbitrarily large scale and that receiving +some funding would dramatically increase the pace and seriousness of the +project - because funded developers can dedicate more of their time to the +project. The involved developers and people stretched outside of the Open +Source ecologies to try to gather as much information and contacts as possible +in order to answer the question: ``Should we go for it?'' to which the answer +quickly became ``Let's see how far we get!''. + +Acting on this strategy proved to be a more difficult task. The entire proposal +and negotiation process took over a year (Autumn 2003 until November 2004).A +proper description of planned work, necessary to satisfy formal requirements, +had not previously been part of the development focus and both the EU and the +parties involved had to adapt to the situation. + +The contract with the EU was signed and the funded part of the project, with +its consortium structure, started 1 of December 2004. The funded part of the +project ends in November 2006. + +The first funded year of the project ended with a review in Brussels in January +2006, hosted by the Commission, reviewing the 10 deliverables comprising the +work of the first year. All deliverables were accepted; based on +recommendations by the external reviewers. The consortium and the Commission is +now restructuring the volume of the remaining the deliverables (although not +changing the scope of the project). + + +%___________________________________________________________________________ + +\hypertarget{influencing-factors-the-f-oss-python-community-culture}{} +\section{Influencing factors: the F/OSS Python community culture} + + +%___________________________________________________________________________ + +\hypertarget{the-python-community}{} +\subsection{The Python community} + +Python is an Open Source language, published under an OSI approved open source +license. It was created by Guido van Rossum and is now one of the five most +used languages in the world. Due to the nature of the language there is a +strong focus on glue and integration with other languages such as C and Java. +Typical aspects of the Python community is that it houses four large +language implementations as separate projects which communicate and discuss +their experiences and approaches with each other. This intra-extra community +focus and interest has created a collaborative atmosphere with an open and +transparent communication climate. + + +%___________________________________________________________________________ + +\hypertarget{the-pypy-community}{} +\subsection{The PyPy community} + +The PyPy project is one of the four large language implementation projects in +the Python community. PyPy grew from the architectural experiences from +previous successful Python projects and this prior community experience was +vital for the evolving of the PyPy community due to the established trust in +expert skills of the core developers starting PyPy - again the people +factor. Thus making it easier recruit people into the PyPy community. + +The PyPy project inherited the focus on collaborative approaches and open +communication climate. The strategy of using sprints, as a core technique, to +kick-start the project as well as moving the sprints to different +locations had clear effects. It encouraged participation by meeting people locally. +During the period of 2003-2004 6 sprints were arranged in various European cities. +These sprints were hosted by universities and private +individuals, participation was funded privately. The effect on the evolving community +was a stable subscriber participation on the development list of between +140-150 people. After the EU-funding and the more systematic structure of +sprinting every 6th week the amount of subscribers went from around 150 people to +over 250 people. Thus turning the prior experience of separate sprints into +a more systematic approach, sprint-driven development. + + +%___________________________________________________________________________ + +\hypertarget{supporting-infrastructure}{} +\subsection{Supporting infrastructure} + +The amount of collaborative focus and open and transparent communication in an +open source community will manifest itself in the supporting infrastructure. +In PyPy version control is the primary means of providing a secure platform for +incremental development. Subversion is used, covering both +program files and documentation. Several automated mailing lists make sure +that every person involved receives instant notification on changes - +supporting peer review on all levels. + +PyPy is also in some sense very much test-driven. PyPy is one of the primary +users of a separate F/OSS project called the py.test, tools for automated +testing with PyPy developers contributing improvements to py.test. Py.test +contains a sophisticated system for running tests against the Python Standard +Library. It provides automatic selection of overriding tests in case there is +internally developed code that overrides the Python Standard Library. These are +important compliance features when the project is about language implementation. +There are also powerful mechanisms for disabling specific +tests and for producing useful traceback output. There are also automatically +generated web pages that show the status of all tests as per the latest checked +in test results. This together with a public issue-tracker covering bugs keeps the +development group focused on the quality of the code when doing +continuous integration. It greatly reduces the need +to coordinate and delegate refactoring work - this is handled in a self-organized way. + +The main communication channels between developers involved in PyPy is to +discuss over IRC (Internet-Relay-Chat) - open for all who are interested. +Several mailing lists for discussions and information are also used. Web pages, +documentation, tutorials, talks and papers etc are all available on the central +developer server for everyone to access. A very useful feature that really supports +information and communication are the public email archives covering the key +mailing lists - going back to the start of 2003. As a newcomer to the project +in the fall of 2003 these public and easily accessible mailing list archives +was the primary means for me personally to get into the project. It provided answers +to who had been key people in the process, what had been crucial topics, how had +discussions and decisions been handled. It is also regularly being used with newcomers +in the development team, providing fast answers to questions and also providing context +to technical decisions being made in the past. A useful just-in-time documentation +and a unorthodox but very efficient way of disseminating information and knowledge. + +Now - all this infrastructure is being used in almost all larger open source +projects and quite a few of them are much more hierarchical and non-transparent +in their communication. In PyPy there is no hierarchy for receiving +commit-rights. A newcomer to PyPy can instantly receive an account on the +development server, with full commit rights to the version control system. The +reason why there are no constraints is that the process is very much +self-organized and managed by the developers from a social level (peer review, +code review, supporting communication channels, coaching, mentoring) and with +strong automated tools covering tests, versions and back ups covering the +technical level. + +An extensive coding guide, published on codespeak.net (development website) +serves as an introduction to the set of specifications being used while coding +PyPy. Yet another piece of the puzzle, the coding guide together with +commit-access to both source code and tests supports cohesion in the development +process. This increases readability and uniformity so that automated testing tools can +be more efficiently used. Again - simple and useful support that is much needed when +working dispersed in a larger team of developers that might never meet face to face. + +In a distributed and dispersed work style these two (social and technical) +levels needs to be consistent and support each other. Discrepancies would be +immediately noticed. As stated before - the people factor is again evident. +If you wish to encourage participation and contribution there has to be trust as +well as a supportive environment in order to manage a virtual collaborative +workspace. The main feature of such a supportive infrastructure is to reduce +the cost of information since coordination and communication is even more difficult +in a dispersed environment. If this easily accessed information of the status of the software +is combined with trust (that is commit-rights) you have the basis for a proactive, +self-organized culture. + + +%___________________________________________________________________________ + +\hypertarget{supporting-practices}{} +\subsection{Supporting practices} + +Another good example of the collaborative nature of the Python community is the +way in which the various projects share best practices. Core developers in the +PyPy project picked up the practice of synchronization meetings as a powerful +way of supporting distributed and dispersed development. This practice was inspired +by the experiences of development processes at Canonical. + +Sync-meetings are weekly short coordination meetings between developers. These are +open to all developers active in the PyPy community, usually but not necessarily +involving aspects of EU-funded work on deliverables. These 30 minute +IRC-meetings serve a weekly synchronization for regular discussions and +integration of ongoing work. Meetings are prepared with an agenda sent out to +pypy-dev and minutes are distributed on pypy-dev and archived in the repository +with publicly accessible links. The work of preparing, managing and documenting the +meetings is rotated between active developers and is self-organized as well. + +Sync-meetings have proved to be a very good complement to a process in which +the project sprints every 6th week. Sync-meetings keep cohesion as well as a +team focus-and-feel for the dispersed work style between sprints. There are three +crucial aspects of this practice. The first one is that our experience as well as +that of Canonical points to keeping the time for the meeting brief. The reason for +30 minutes limit is that it gives priority on what topics to choose. However +complex your development situation is you should choose not more than 3 topics, +topics that could be discussed and decided upon during these 30 minutes. Not having +this time limit would create long and tiresome IRC meetings which would affect motivation +people and also create more confusion than results. + +The second aspect is that it has a fixed format in which the meeting starts with +all developers participating in the meeting presents a very short status - answering +the questions LAST (last week), NEXT (their focus for the upcoming week) +and BLOCKERS (if they are stuck and need help). This means that the group get +overview and can track progress, albeit loosely. All individuals get an opportunity to +voice their personal situation and the group jointly discuss potential blockers and how +to solve them. The fixed format help to keep focus and creates a rhythm that makes it +easier for newcomers to get into the flow of the meeting. + +The third aspect is also the main challenge with the practice. In PyPy we rotate +the organization of the meetings between the developers. But because meeting +moderation has to do with experience, people skills as well as a certain overview of +the project not everyone can actually do this task. Our experience shows that it is +also very important to have core people involved in identifying topics needing to be +discussed - having the progress of the project in mind. It is very easy to choose +topics that do not need the group mind to discuss, that are too detailed, that has +too much focus on information distribution rather than discussions. + +Here is what one of the new core developers of PyPy says about sync-meetings: +\begin{quote} + +\emph{``Sync-meetings are useful because they enable developers to discuss and +clarify issues among themselves and to provide a common focus when working +distributedly. They are also a lightweight way to synchronize activities, +resolve blockers and to get an overview about who is currently doing what +work.''} +-- Carl Friedrich Bolz +\end{quote} + + +%___________________________________________________________________________ + +\hypertarget{influencing-factors-agile-practices-in-pypy}{} +\section{Influencing factors: agile practices in PyPy} + + +%___________________________________________________________________________ + +\hypertarget{sprints}{} +\subsection{Sprints} + +PyPy first started during a one-week meeting, a ``sprint'', held at Trillke-Gut +in Hildesheim February 2003. The sprint was inspired by practices used by other +Python projects such as Zope3. Originally the sprint methodology used in the +Python community grew from practices applied by the Zope Corporation. Their +definition of a sprint was: ``two-day or three-day focused development session, +in which developers pair off together in a room and focus on building a +particular subsystem''. + +Tres Seaver of the Zope Community, one of the instigators of the sprint +method as it is used in the Python community says the following about how they +evolved the method during 2001 and 2002: +\begin{quote} + +\emph{``The motivation was to begin using as much of XP as would fit to +accelerate Zope3 development. Given the different development culture of +the Zope community (framework-centric, distributed, no ''business user`` +present), some of the XP mantras /practices couldn't be done directly. We +decided to try to do ''as much XP as possible`` for short, highly-focused +sessions, with all active committers collocated.''} +\end{quote} + +The Zope community as well as other Python projects such as PyPy have seen that +sprints generate results beyond the creation of software: +\begin{itemize} +\item {} +It helped to evolve the community through participation and hands-on contact +with the core developers. + +\item {} +It is a live training session not only in producing code but also in the +development methods being used (the sprint method in itself, pair programming +and TDD). + +\item {} +It supports activities such as design decisions and high-level requirements +discussions, creating cohesion and understanding as well as minimizing risks +with dispersed/distributed work where these kind of activities can be really +difficult to manage. + +\end{itemize} + +In order to provide examples - in PyPy these discussion sessions have been done in +various different ways during sprints. The proposal for the EU and the work package +descriptions were drafted through group discussions during sprints. Later sprints in which +the process needed design decisions, developers paired up in several groups of 2-4 +people per group for daily discussion sessions. These sessions ended with brief +documentation and presentations for the other groups where decisions were made. +Usually what happens is that the daily sprint planning results in a pair of core developers +choosing a topic to discuss. These discussions have even acted as tutorials for other +developers sitting in and following the discussions. Some of these discussions have also +been filmed for dissemination purposes. + +The reason for naming the method sprinting, is not at all connected to Scrum and +the usage of sprints in that context, according to Tres Seaver is: +\begin{quote} + +\emph{``... because of the fact that we weren't doing XP in its proper sense, +which is more like running a long-distance race, where pacing oneself is +critical. Instead, we were pushing as fast as possible in order to +maximize the benefit of limited face time. Of all the XP practices, the +one we gave shortest shrift to is ''no overtime``: as sprints often go far +into the evening (or even the wee hours of the morning.''} +\end{quote} + +To summarize the results of this first try out of the methodology shows that +sprinting was the driver for making Zope3 a community-driven project: Zope +Corporation in fact ceded control over the development process to the new +``Zope3 core'' group created via sprinting. Less than 2 years later the same effect +was to be found in the F/OSS project PyPy - the community evolved through +sprint driven development. + +The sprint method, as well as key aspects of F/OSS supportive infrastructure +and practices was established within the project before PyPy received its +EU-funding. Thus, in the proposal,we put much emphasis on the methodology in +itself when designing the consortium level process. Examples of how this was +done was that we created a methodology objective, specific deliverables +regarding documentation of the sprint-driven methodology as well as designing a +process during the 2 years of funding in which the project and the developers +sprints every 6th week. This was taken into account when estimating the budget, +adding costs for travel and accommodation for all partner organizations - +covering 14 sprints during the 2 years. So far during the funded part of the +project we have organized 10 sprints - successful sprints from both a +development, recruiting, dissemination and networking aspects. Another +important fact is that the sprints are organized by the developers and as such +is another good example of the collaborative manner of the culture of the +project and the community. + +Why did PyPy choose sprinting as a key technique? It is a method that fits +distributed teams well because it gets the team focused around visible +challenging goals while working collaboratively (pair-programming, status +meetings, discussions etc) as well as accelerated (short increments and tasks, +``doing'' and testing instead of long startups of planning and requirement +gathering, continuous integration). This means that most of the time a sprint +is a great way of getting results and getting new people acquainted - a good +method for dissemination of knowledge and learning within the team. + +Another insight, worthwhile for other more discipline based projects to ponder, +is how an agile process like sprinting is much more suited for creative work +between groups of distributed people. Traditional software development, as well +as traditional project management techniques have a tendency to hinder creativity +due to the inbuilt over-structured, segmented and control-oriented approach +which in most cases ends in less quality when results are being measured. + + +%___________________________________________________________________________ + +\hypertarget{eu-project-practices}{} +\section{EU-project practices} + + +%___________________________________________________________________________ + +\hypertarget{consortium-structure}{} +\subsection{Consortium structure} + +Key requirements regarding organizational structures of a Framework Programme +6 EU-project are: +\begin{itemize} +\item {} +a consortium of partners performing the work described in the contract + +\item {} +a project co-coordinator managing contract administration and communication +between consortium and the Commission + +\item {} +a project manager, responsible for the project reaching its goals within the +time frame and budget + +\end{itemize} + +The challenge was to design a project process that created a minimal amount of +changes to the structure being in use in the F/OSS project. It was especially +important to maintain an open and transparent communication, even for decision +on consortium level and such. There was a fear of the EU-project adding +``top-down'' structures on the F/OSS work and on the core developers instigating +the project. + +We identified a minimalistic approach of management roles (project +co-coordinator, project manager, assistant project manager) and created a +management team to make sure that there was collaboration between these roles. +Although the responsibility rested on the different management roles and the +management team the strategy implemented was to delegate as much as possible of +the responsibilities and decision-making to the core developers. + +The strategy was to keep ``conceptual integrity'' \cite{key-2} of +the vision and the idea in the hands of the core developers. As Brooks +stresses, a uniform system design is better than uncoordinated and independent +design ideas. The core developers had a clear and agreed vision - but would +they be allowed to implement it within a fixed contract work style, with new +partners involved that had not been involved in the process from the start? The +core developers were organized into a technical board, responsible for planning +and coordinating the development work between the partners, with the mandate to +make decisions. A somewhat negative result was the added workload and +responsibility on developers regarding EU related work. + +This structure was the most difficult to design and implement due to the very +different nature of its purpose compared to the collaborative, self-organized +nature of the F/OSS project - again it succeeded the way it has because of the +core developers acting as an interface between the developer group and the +consortium level work - again we see the trust aspect and the people factor in +play. + +Sprints were budgeted for and designed into the process, together with a +time plan for all deliverables. The project was divided into three different +phases, depending on the nature of the work flow. In that sense we could +describe the EU-part of the project as a fixed-contract style of work, but with +time plan, deliverables and work package descriptions on a high-level, not +broken down into more granular tasks. + + +%___________________________________________________________________________ + +\hypertarget{communication-and-documentation}{} +\subsection{Communication and documentation} + +All documentation and supporting communication infrastructure is hosted on the +same developer server as the source code, covered by the same version control +system. Only a few repositories are not publically available (such as the resource +tracking repositories) - but they are fully accessible for everyone employed by +a partner organization. + +The communication infrastructure being used on the consortium level of work +mirrors that of the development work - having years of experience on the +distributed work style. In the case of PyPY there are mailing lists as well as +IRC channels for consortium level work. We even implemented a procedure in our +internal consortium agreement to allow for virtual meetings for decisions in +the consortium. So far this have been the primary meeting form and it has +worked well as a channel for making decisions. IRC-logs and minutes support the +procedure. In some cases decisions have also been made via email on the +consortium mailing list. + +Although not the primary focus it is also useful to have the regular sprints to +coordinate specific issues between some partners or between all partners, have +physical meetings and discussions between the management team and the technical +board etc. + +Our funding have also resulted in the possibility to have a more unorthodox approach +to documentation - the project have experimented in filming sprints to show the +development method as well as filming talks and discussion. Our film material +is planned to be released before summer 2006. + + +%___________________________________________________________________________ + +\hypertarget{troubles-in-paradise-striking-a-balance}{} +\section{Troubles in Paradise: striking a balance} + + +%___________________________________________________________________________ + +\hypertarget{developer-driven-versus-formal-project-structure}{} +\subsection{Developer driven versus formal project structure} + +The fear of a top-down, hierarchical decision process of the consortium was a +justified one. It is interesting for us to note that now, having the +experience and more contractual overview to note that there is nothing in the +requirements from the Commission that forces a project to a more traditional +and strict project process. It is mostly a question of the experience and +customs of the partner companies. In that sense there was much flexibility in +designing a process that allowed for a developer driven process regarding not +only software development but also sprint administration and planning as well +as consortium work. + +The majority of the partners with key roles in the consortium organization had +been working together since before the funding. In that sense procedures and best +practices had been tried out. The results from the first year showed that a minimalistic +path could be identified and that the important work would be to review and +adjust the process when it did not support the work any more, or new situations +arose that we had not planned for (and that did happen!). + +Already year two has another look-and-feel to it on a consortium level when it +comes to how the management team and the technical board works, because of the +different nature of work in year two. + + +%___________________________________________________________________________ + +\hypertarget{agile-strategies-versus-formal-eu-contractual-requirements}{} +\subsection{Agile strategies versus formal EU-contractual requirements} + +Our main agile practice, sprint-driven development, was successfully integrated +into the formal contractual requirements, allowing for the same free-floating +agile process of self organizing and decision making as existed before the +funding, but with a more systematic and documented style. + +But here is also our biggest failure, the main ``un-agile'' aspect of the entire +project having a large negative effect not only on the EU-part of the project +but also on the community. We had planned for a process that kept an +``open-door'' policy that allowed us to fund non-consortium persons from the +community to attend sprints. The budget was allocated, the procedure within the +sprint context of handling more newcomers were known to us - the main +show stopper was that the PyPy sprint funding did not fit within the customs and +practices of contracts for cost claims in the Commission. + +Every time we want to encourage participation and fund non-consortium +people to participate in sprints and contribute, the procedure now is that +they have to join the consortium as a full partner. +This creates the need for a contractual amendment with the Commission which +adds administrative work to the project as well as for the persons in question. +A too blunt instrument and today we still do not have a working solution to this +problem. It is an unfortunate example on how the influencing factor of F/OSS, +agile practices and EU-funding collides and creates negative impact on the project. + + +%___________________________________________________________________________ + +\hypertarget{f-oss-community-versus-hierarchies-for-conceptual-integrity}{} +\subsection{F/OSS community versus hierarchies for ``conceptual integrity''} + +There are many examples of F/OSS projects and communities that have dried out +because of the fear of the architects to allow the contributors to fully +participate and also influence features and visions of the software. In PyPy +this challenge comes twofold. Not only is there a challenge to let the core +developers keep ``conceptual integrity'' while also allowing the community to +influence the direction and features of the software. There is also the +consortium level of work in which the core developers could fear to ``lose'' the +mandate of driving the architectural and design work. And yet another layer of +risk and complexity would be if the consortium level would ``shut the door'' on +the community, enforcing a more closed development process. + +As in many cases - being risk aware is the first step to mitigation. Because the +project is so deeply rooted in the F/OSS Python community, with its specific +culture and climate, and because so many people involved in the core work on +both the development and consortium level also shared this background they took +great pains to avoid situations like this to happen. In fact, what we have +realized only some months ago is that there is another risk, already partly +having effect on the community. Because of the funding the development process +is progressing much more rapidly in PyPy than more normal F/OSS projects. The +speed and the dramatically increasing learning curve could make members more +passive because they do not have the time to follow full-time IRC discussions, +postings on mailing lists and the actual source code and increasing test suites. + +This is a challenge and it is the focus of the developer group to try to +distill and package information in order to help people to better navigate the +progress. + + +%___________________________________________________________________________ + +\hypertarget{conclusion}{} +\section{Conclusion} + +The important question is the following (and is also part of the methodological +objective of the project): is there enough room to manage a project and Open +Source community within the plan-driven inspired methods that are required in +EU-funded projects, while still working agile and distributed? + +We believe so. The one clear dominating factor to make all this succeed is, as +always, the people factor, the CRACK performers as Boehm and Turner calls them +(``Collaborative, Representative, Authorized, Committed, Knowledgeable'') +\cite{key-3}. + +The core developers of the PyPy project had the right mix of various skills in +order to succeed in setting up a hybrid environment - enabling them to work +full time on a project they strongly believed in. The most crucial mix of +skills for making this possible was/are: +\begin{itemize} +\item {} +\textbf{Social:} The ability to communicate open and transparent, to mentor and +tutor dispersed as well as reinventing different collaborative work styles of +the sprint method, ``manage'' groups and community as well as consortium, and +handle conflicts) + +\item {} +\textbf{Leadership abilities:} The ability to step into formal leadership roles in +technical board structures, manage sprints and sync-meetings as well as the +more informal management of the community of developers. Managing the balance +between encouraging participation but still holding true to their vision, +their ``conceptual integrity''. + +\item {} +\textbf{Ability to network:} To be open to other communities, inviting new +partners in order to create a working consortium structure in the EU-project, +curious and collaborative towards other Python implementations and other +languages and research approaches, sharing knowledge and experiences and +seeking bets practices of other projects. + +\item {} +\textbf{Entrepreneurs:} To risk the community through pursuing the idea of +EU-funding in order to fulfill the ambitious vision, managing to not only +create a consortium with innovative structures of cooperation but also to +create new companies. + +\item {} +\textbf{Technical skills:} Programming language and implementation +aspects,frameworks, mathematics, computer science - core skills for the +project. Also the ability to design, setup and effectively manage supporting +infrastructure for the development process. + +\item {} +Managing the balance between encouraging participation but still holding true +to their vision, their ``\textbf{conceptual integrity}'' This while working agile with +open and transparent communication through sprints, documentation, tutorials, +mentoring, sync-meetings. Resulting in a lively and growing the F/OSS +community around the project. + +\end{itemize} + +So, could it be said that for an agile software development process, especially +one that is distributed and community oriented, within a framework of +EU-funding, that it is heavily people dependent? Or to stress it even further, +sprint-driven development as a methodology does not exist and function without +an agile group of people, Crack performers. The people are the methodology in +some sense and if you wish to draw upon the experience of the PyPy team you +need to look at the supporting practices around the people in order to find +what can be duplicated and tested in another project environment. This +conclusion matches what Alistair Cockburn writes in his paper ``Characterizing +People as Non-Linear, First-Order Components in Software Development'' +\cite{key-4}: +\begin{quote} + +\emph{``The fundamental characteristics of ''people`` have a first-order +effect on software development, not a lower-order effect.''} +\end{quote} + +If we accept this conclusion then we can also, thanks to the people, start to +get innovative regarding practices. Designing the project process based on the +specific needs of the unique project environment you are facing. In the case of +PyPy this means that we are exploring the methodology as we go along, adjusting +and fine tuning the process as well as the software. + +So, when drawing from these different skills within the community of +developers, the people, in the PyPy project one possible conclusion would be +that a truly agile approach dominating the work style of an Open Source project +will increase the ability of the community to spread the strategy of agility to +other domains. + +By this we mean that what started as agile practices in the development process +quickly became influencing factors when designing other project processes. +Examples of this in PyPy is how the sprint-driven development acts as a focal +point not just for the development work (co-located as well as dispersed) but +also for the formal and informal management of the project. Sprints together +with the CRACK performers was what made the community grow and evolve. It was +the foundation for a hybrid project where agile practices and EU-funding can +fit within a distributed Open Source context. + + +%___________________________________________________________________________ + +\hypertarget{acknowledgments}{} +\section{Acknowledgments} + +The author would like to thank the following people who have in various ways +helped with the creation of this paper: Angela Martin, Emily Bache, Tres +Seaver, Carl Friedrich Bolz. + +I would like to dedicate this paper to my dear friend and mentor of the Open +Source Python and PyPy community Holger Krekel. +% References: +% =========== +\begin{thebibliography}{1} + + \bibitem{key-1} Beatrice D?ring, "Sprint-Driven Development: Agile methodologies + in a Distributed Open Source Project (PyPy)", XP 2006 + +\bibitem{key-2} Fredrick P. Brooks, Jr, "The mythical man-month, anniversary +edition", Addison-Wesley, 1995 + +\bibitem{key-3} Barry Boehm,Richard Turner, "Observations on Balancing +Discipline and Agility", (drawn from the book "Balancing Agility and +Discipline: A Guide to the Perplexed", Addison Wesley, 2003) + +\bibitem{key-4} Alistair Cockburn, "Characterizing People as Non-Linear, First-Order +Components in Software Development", Presented at the 4th International +Multi-Conference on Systems, Cybernetics and Informatics, Orlando, +Florida, June, 2000, \texttt{http://alistair.cockburn.us/crystal/\\ +articles/cpanfocisd/\\ +characterizingpeopleasnonlinear.html} + +\end{thebibliography} +\end{document} From cfbolz at codespeak.net Sat May 6 12:53:53 2006 From: cfbolz at codespeak.net (cfbolz at codespeak.net) Date: Sat, 6 May 2006 12:53:53 +0200 (CEST) Subject: [pypy-svn] r26857 - pypy/extradoc/talk/agile2006 Message-ID: <20060506105353.143301007B@code0.codespeak.net> Author: cfbolz Date: Sat May 6 12:53:51 2006 New Revision: 26857 Modified: pypy/extradoc/talk/agile2006/draftpaper_agile2006.tex (props changed) Log: FIXEOL From arigo at codespeak.net Sat May 6 13:18:39 2006 From: arigo at codespeak.net (arigo at codespeak.net) Date: Sat, 6 May 2006 13:18:39 +0200 (CEST) Subject: [pypy-svn] r26858 - in pypy/dist/pypy/objspace/std: . test Message-ID: <20060506111839.5FA181007E@code0.codespeak.net> Author: arigo Date: Sat May 6 13:18:37 2006 New Revision: 26858 Added: pypy/dist/pypy/objspace/std/smallintobject.py - copied, changed from r26843, pypy/dist/pypy/objspace/std/intobject.py pypy/dist/pypy/objspace/std/test/test_smallintobject.py - copied, changed from r26843, pypy/dist/pypy/objspace/std/test/test_intobject.py Modified: pypy/dist/pypy/objspace/std/boolobject.py pypy/dist/pypy/objspace/std/inttype.py pypy/dist/pypy/objspace/std/model.py Log: Added "small integers" as a tagged, odd-valued pointer. Disabled by default, see WITHSMALLINT. Gives a small slow-down in pypy-c. Some more optimizations could be done in rtagged.py, though. Modified: pypy/dist/pypy/objspace/std/boolobject.py ============================================================================== --- pypy/dist/pypy/objspace/std/boolobject.py (original) +++ pypy/dist/pypy/objspace/std/boolobject.py Sat May 6 13:18:37 2006 @@ -1,5 +1,5 @@ from pypy.objspace.std.objspace import * -from pypy.objspace.std.inttype import wrapint +from pypy.objspace.std.intobject import W_IntObject class W_BoolObject(W_Object): @@ -22,8 +22,12 @@ # bool-to-int delegation requires translating the .boolvar attribute # to an .intval one -def delegate_Bool2Int(space, w_bool): - return wrapint(int(w_bool.boolval)) +def delegate_Bool2IntObject(space, w_bool): + return W_IntObject(int(w_bool.boolval)) + +def delegate_Bool2SmallInt(space, w_bool): + from pypy.objspace.std.smallintobject import W_SmallIntObject + return W_SmallIntObject(int(w_bool.boolval)) # cannot overflow def nonzero__Bool(space, w_bool): Modified: pypy/dist/pypy/objspace/std/inttype.py ============================================================================== --- pypy/dist/pypy/objspace/std/inttype.py (original) +++ pypy/dist/pypy/objspace/std/inttype.py Sat May 6 13:18:37 2006 @@ -3,9 +3,23 @@ from pypy.interpreter.error import OperationError from pypy.interpreter.gateway import NoneNotWrapped -def wrapint(x): - from pypy.objspace.std.intobject import W_IntObject - return W_IntObject(x) +# ____________________________________________________________ + +from pypy.objspace.std.model import WITHSMALLINT +if WITHSMALLINT: + def wrapint(x): + from pypy.objspace.std.smallintobject import W_SmallIntObject + try: + return W_SmallIntObject(x) + except OverflowError: + from pypy.objspace.std.intobject import W_IntObject + return W_IntObject(x) +else: + def wrapint(x): + from pypy.objspace.std.intobject import W_IntObject + return W_IntObject(x) + +# ____________________________________________________________ def retry_to_w_long(space, parser, base=0): parser.rewind() @@ -85,6 +99,9 @@ space.wrap( "long int too large to convert to int")) return w_longval + elif space.is_w(w_inttype, space.w_int): + # common case + return wrapint(value) else: w_obj = space.allocate_instance(W_IntObject, w_inttype) W_IntObject.__init__(w_obj, value) Modified: pypy/dist/pypy/objspace/std/model.py ============================================================================== --- pypy/dist/pypy/objspace/std/model.py (original) +++ pypy/dist/pypy/objspace/std/model.py Sat May 6 13:18:37 2006 @@ -9,6 +9,7 @@ import pypy.interpreter.special WITHSET = False +WITHSMALLINT = False class StdTypeModel: @@ -49,6 +50,8 @@ from pypy.objspace.std import complexobject if WITHSET: from pypy.objspace.std import setobject + if WITHSMALLINT: + from pypy.objspace.std import smallintobject from pypy.objspace.std import tupleobject from pypy.objspace.std import listobject from pypy.objspace.std import dictobject @@ -92,6 +95,8 @@ self.typeorder[setobject.W_SetObject] = [] self.typeorder[setobject.W_FrozensetObject] = [] self.typeorder[setobject.W_SetIterObject] = [] + if WITHSMALLINT: + self.typeorder[smallintobject.W_SmallIntObject] = [] for type in self.typeorder: self.typeorder[type].append((type, None)) @@ -104,8 +109,19 @@ # register the order in which types are converted into each others # when trying to dispatch multimethods. # XXX build these lists a bit more automatically later + if WITHSMALLINT: + self.typeorder[boolobject.W_BoolObject] += [ + (smallintobject.W_SmallIntObject, boolobject.delegate_Bool2SmallInt), + ] + self.typeorder[smallintobject.W_SmallIntObject] += [ + (intobject.W_IntObject, smallintobject.delegate_SmallInt2Int), + (longobject.W_LongObject, smallintobject.delegate_SmallInt2Long), + (floatobject.W_FloatObject, smallintobject.delegate_SmallInt2Float), + (complexobject.W_ComplexObject, smallintobject.delegate_SmallInt2Complex), + ] + self.typeorder[boolobject.W_BoolObject] += [ - (intobject.W_IntObject, boolobject.delegate_Bool2Int), + (intobject.W_IntObject, boolobject.delegate_Bool2IntObject), (longobject.W_LongObject, longobject.delegate_Bool2Long), (floatobject.W_FloatObject, floatobject.delegate_Bool2Float), (complexobject.W_ComplexObject, complexobject.delegate_Bool2Complex), From arigo at codespeak.net Sat May 6 13:21:29 2006 From: arigo at codespeak.net (arigo at codespeak.net) Date: Sat, 6 May 2006 13:21:29 +0200 (CEST) Subject: [pypy-svn] r26859 - in pypy/dist/pypy/translator: . backendopt backendopt/test c llvm test Message-ID: <20060506112129.C6CC71007E@code0.codespeak.net> Author: arigo Date: Sat May 6 13:21:27 2006 New Revision: 26859 Modified: pypy/dist/pypy/translator/backendopt/all.py pypy/dist/pypy/translator/backendopt/test/test_propagate.py pypy/dist/pypy/translator/c/funcgen.py pypy/dist/pypy/translator/c/node.py pypy/dist/pypy/translator/driver.py pypy/dist/pypy/translator/interactive.py pypy/dist/pypy/translator/llvm/genllvm.py pypy/dist/pypy/translator/test/test_interactive.py Log: Don't to SSI_to_SSA() at the end of backendopt.all(). Instead, the C back-end does it on the graph at the very last minute. This allows the extra code introduced by GC and exception transforms to benefit from it too. Modified: pypy/dist/pypy/translator/backendopt/all.py ============================================================================== --- pypy/dist/pypy/translator/backendopt/all.py (original) +++ pypy/dist/pypy/translator/backendopt/all.py Sat May 6 13:21:27 2006 @@ -2,7 +2,6 @@ from pypy.translator.backendopt import removenoops from pypy.translator.backendopt.inline import auto_inlining from pypy.translator.backendopt.malloc import remove_simple_mallocs -from pypy.translator.backendopt.ssa import SSI_to_SSA from pypy.translator.backendopt.propagate import propagate_all from pypy.translator.backendopt.stat import print_statistics from pypy.translator.backendopt.merge_if_blocks import merge_if_blocks @@ -16,7 +15,6 @@ def backend_optimizations(translator, raisingop2direct_call_all=False, inline_threshold=1, mallocs=True, - ssa_form=True, merge_if_blocks_to_switch=True, propagate=False, heap2stack=False, @@ -93,8 +91,4 @@ print "after if-to-switch:" print_statistics(translator.graphs[0], translator) - if ssa_form: - for graph in translator.graphs: - SSI_to_SSA(graph) - translator.checkgraphs() Modified: pypy/dist/pypy/translator/backendopt/test/test_propagate.py ============================================================================== --- pypy/dist/pypy/translator/backendopt/test/test_propagate.py (original) +++ pypy/dist/pypy/translator/backendopt/test/test_propagate.py Sat May 6 13:21:27 2006 @@ -12,7 +12,7 @@ t.buildrtyper().specialize() if all_opts: backend_optimizations(t, inline_threshold=inline_threshold, - ssa_form=False, propagate=False) + propagate=False) graph = graphof(t, fn) if conftest.option.view: t.view() @@ -234,7 +234,7 @@ def test_call_list_default_argument(): graph, t = get_graph(call_list_default_argument, [int]) - backend_optimizations(t, propagate=True, ssa_form=False) + backend_optimizations(t, propagate=True) for i in range(10): check_graph(graph, [i], call_list_default_argument(i), t) if conftest.option.view: Modified: pypy/dist/pypy/translator/c/funcgen.py ============================================================================== --- pypy/dist/pypy/translator/c/funcgen.py (original) +++ pypy/dist/pypy/translator/c/funcgen.py Sat May 6 13:21:27 2006 @@ -9,6 +9,7 @@ from pypy.rpython.lltypesystem.lltype import UnsignedLongLong, Char, UniChar from pypy.rpython.lltypesystem.lltype import pyobjectptr, ContainerType from pypy.rpython.lltypesystem.lltype import Struct, Array, FixedSizeArray +from pypy.translator.backendopt.ssa import SSI_to_SSA PyObjPtr = Ptr(PyObject) LOCALVAR = 'l_%s' @@ -101,9 +102,10 @@ # for op in block.operations: # op.args = tuple(op.args) self.db.gctransformer.inline_helpers(newgraph) - self.collect_var_and_types() else: self.oldgraph = self.graph + SSI_to_SSA(self.graph) + self.collect_var_and_types() self.blocknum = {} for block in self.graph.iterblocks(): self.blocknum[block] = len(self.blocknum) Modified: pypy/dist/pypy/translator/c/node.py ============================================================================== --- pypy/dist/pypy/translator/c/node.py (original) +++ pypy/dist/pypy/translator/c/node.py Sat May 6 13:21:27 2006 @@ -585,7 +585,10 @@ def funcgen_implementation(self, funcgen): funcgen.implementation_begin() - yield '%s {' % cdecl(self.implementationtypename, funcgen.name(self.name)) + # recompute implementationtypename as the argnames may have changed + argnames = funcgen.argnames() + implementationtypename = self.db.gettype(self.T, argnames=argnames) + yield '%s {' % cdecl(implementationtypename, funcgen.name(self.name)) # # declare the local variables # Modified: pypy/dist/pypy/translator/driver.py ============================================================================== --- pypy/dist/pypy/translator/driver.py (original) +++ pypy/dist/pypy/translator/driver.py Sat May 6 13:21:27 2006 @@ -206,7 +206,7 @@ def task_backendopt(self): from pypy.translator.backendopt.all import backend_optimizations opt = self.options - backend_optimizations(self.translator, ssa_form=opt.backend != 'llvm', + backend_optimizations(self.translator, merge_if_blocks_to_switch=opt.merge_if_blocks) # task_backendopt = taskdef(task_backendopt, Modified: pypy/dist/pypy/translator/interactive.py ============================================================================== --- pypy/dist/pypy/translator/interactive.py (original) +++ pypy/dist/pypy/translator/interactive.py Sat May 6 13:21:27 2006 @@ -138,7 +138,7 @@ def backendopt(self, argtypes=None, **kwds): self.update_options(argtypes, kwds) - self.ensure_backend() + #self.ensure_backend() self.driver.backendopt() def backendopt_c(self, argtypes=None, **kwds): Modified: pypy/dist/pypy/translator/llvm/genllvm.py ============================================================================== --- pypy/dist/pypy/translator/llvm/genllvm.py (original) +++ pypy/dist/pypy/translator/llvm/genllvm.py Sat May 6 13:21:27 2006 @@ -314,9 +314,9 @@ t.buildannotator().build_types(function, annotation) t.buildrtyper().specialize() if optimize: - backend_optimizations(t, ssa_form=False) + backend_optimizations(t) else: - backend_optimizations(t, ssa_form=False, + backend_optimizations(t, inline_threshold=0, mallocs=False, merge_if_blocks_to_switch=False, Modified: pypy/dist/pypy/translator/test/test_interactive.py ============================================================================== --- pypy/dist/pypy/translator/test/test_interactive.py (original) +++ pypy/dist/pypy/translator/test/test_interactive.py Sat May 6 13:21:27 2006 @@ -52,7 +52,7 @@ t.backendopt_c() t = Translation(f, [int, int]) - py.test.raises(Exception, "t.backendopt()") + t.backendopt() def test_simple_source(): def f(x, y): From cfbolz at codespeak.net Sat May 6 13:42:16 2006 From: cfbolz at codespeak.net (cfbolz at codespeak.net) Date: Sat, 6 May 2006 13:42:16 +0200 (CEST) Subject: [pypy-svn] r26863 - pypy/extradoc/talk/agile2006 Message-ID: <20060506114216.6A1DB10080@code0.codespeak.net> Author: cfbolz Date: Sat May 6 13:42:08 2006 New Revision: 26863 Modified: pypy/extradoc/talk/agile2006/draftpaper_agile2006.dvi pypy/extradoc/talk/agile2006/draftpaper_agile2006.pdf Log: regenerate pdf to not contain link Modified: pypy/extradoc/talk/agile2006/draftpaper_agile2006.dvi ============================================================================== Binary files. No diff available. Modified: pypy/extradoc/talk/agile2006/draftpaper_agile2006.pdf ============================================================================== Binary files. No diff available. From bea at codespeak.net Sat May 6 13:55:00 2006 From: bea at codespeak.net (bea at codespeak.net) Date: Sat, 6 May 2006 13:55:00 +0200 (CEST) Subject: [pypy-svn] r26864 - pypy/extradoc/talk/agile2006 Message-ID: <20060506115500.D20DE1007E@code0.codespeak.net> Author: bea Date: Sat May 6 13:54:41 2006 New Revision: 26864 Added: pypy/extradoc/talk/agile2006/during-oss_sprints.pdf (contents, props changed) Log: final file name Added: pypy/extradoc/talk/agile2006/during-oss_sprints.pdf ============================================================================== Binary file. No diff available. From arigo at codespeak.net Sat May 6 14:35:22 2006 From: arigo at codespeak.net (arigo at codespeak.net) Date: Sat, 6 May 2006 14:35:22 +0200 (CEST) Subject: [pypy-svn] r26868 - pypy/dist/pypy/translator/backendopt Message-ID: <20060506123522.B55331007E@code0.codespeak.net> Author: arigo Date: Sat May 6 14:35:21 2006 New Revision: 26868 Modified: pypy/dist/pypy/translator/backendopt/propagate.py Log: Renamed veeery confusing function. Modified: pypy/dist/pypy/translator/backendopt/propagate.py ============================================================================== --- pypy/dist/pypy/translator/backendopt/propagate.py (original) +++ pypy/dist/pypy/translator/backendopt/propagate.py Sat May 6 14:35:21 2006 @@ -133,7 +133,7 @@ raise TooManyOperations return super(CountingLLFrame, self).eval_operation(operation) -def op_can_be_folded(op): +def op_dont_fold(op): try: return not lloperation.LL_OPERATIONS[op.opname].canfold except KeyError: @@ -169,7 +169,7 @@ if (called_graph is not None and simplify.has_no_side_effects( translator, called_graph, - is_operation_false=op_can_be_folded) and + is_operation_false=op_dont_fold) and (block.exitswitch != c_last_exception or i != len(block.operations) - 1)): args = [arg.value for arg in op.args[1:]] From arigo at codespeak.net Sat May 6 15:06:44 2006 From: arigo at codespeak.net (arigo at codespeak.net) Date: Sat, 6 May 2006 15:06:44 +0200 (CEST) Subject: [pypy-svn] r26871 - in pypy/dist/pypy: rpython translator/backendopt Message-ID: <20060506130644.6695D1007E@code0.codespeak.net> Author: arigo Date: Sat May 6 15:06:42 2006 New Revision: 26871 Modified: pypy/dist/pypy/rpython/llinterp.py pypy/dist/pypy/translator/backendopt/propagate.py Log: Cleanups. Details. Modified: pypy/dist/pypy/rpython/llinterp.py ============================================================================== --- pypy/dist/pypy/rpython/llinterp.py (original) +++ pypy/dist/pypy/rpython/llinterp.py Sat May 6 15:06:42 2006 @@ -351,10 +351,7 @@ break else: raise TypeError("the operation %s is not expected to raise %s" % (operation, exc)) - self.handle_cleanup(operation, exception=True) raise - else: - self.handle_cleanup(operation) self.setvar(operation.result, retval) if tracer: if retval is None: @@ -362,16 +359,6 @@ else: tracer.dump(' ---> %r\n' % (retval,)) - def handle_cleanup(self, operation, exception=False): - cleanup = getattr(operation, 'cleanup', None) - if cleanup is not None: - cleanup_finally, cleanup_except = cleanup - for op in cleanup_finally: - self.eval_operation(op) - if exception: - for op in cleanup_except: - self.eval_operation(op) - def make_llexception(self, exc=None): if exc is None: original = sys.exc_info() Modified: pypy/dist/pypy/translator/backendopt/propagate.py ============================================================================== --- pypy/dist/pypy/translator/backendopt/propagate.py (original) +++ pypy/dist/pypy/translator/backendopt/propagate.py Sat May 6 15:06:42 2006 @@ -134,6 +134,10 @@ return super(CountingLLFrame, self).eval_operation(operation) def op_dont_fold(op): + if op.opname in ('getfield', 'getarrayitem'): + CONTAINER = op.args[0].concretetype.TO + if CONTAINER._hints.get('immutable'): + return False try: return not lloperation.LL_OPERATIONS[op.opname].canfold except KeyError: From arigo at codespeak.net Sat May 6 15:43:02 2006 From: arigo at codespeak.net (arigo at codespeak.net) Date: Sat, 6 May 2006 15:43:02 +0200 (CEST) Subject: [pypy-svn] r26872 - pypy/dist/pypy/translator/backendopt Message-ID: <20060506134302.D48CA1007E@code0.codespeak.net> Author: arigo Date: Sat May 6 15:43:02 2006 New Revision: 26872 Modified: pypy/dist/pypy/translator/backendopt/propagate.py Log: Last check-in here for now: missed a couple of other places that should also use op_dont_fold(). Modified: pypy/dist/pypy/translator/backendopt/propagate.py ============================================================================== --- pypy/dist/pypy/translator/backendopt/propagate.py (original) +++ pypy/dist/pypy/translator/backendopt/propagate.py Sat May 6 15:43:02 2006 @@ -152,8 +152,9 @@ for i, op in enumerate(block.operations): if sum([isinstance(arg, Variable) for arg in op.args]): continue - if op.opname in lloperation.LL_OPERATIONS and lloperation.LL_OPERATIONS[op.opname].canfold: + if not op_dont_fold(op): if op.opname in ("getsubstruct", "getarraysubstruct"): + # XXX why this case? if not var_needsgc(op.result): continue try: @@ -208,8 +209,7 @@ return usedvars = {} for op in block.operations: - if (op.opname not in lloperation.LL_OPERATIONS or - not lloperation.LL_OPERATIONS[op.opname].canfold): + if op_dont_fold(op): return for arg in op.args: if (isinstance(arg, Variable) and arg in block.inputargs): From cfbolz at codespeak.net Sat May 6 16:15:58 2006 From: cfbolz at codespeak.net (cfbolz at codespeak.net) Date: Sat, 6 May 2006 16:15:58 +0200 (CEST) Subject: [pypy-svn] r26875 - in pypy/dist/pypy/translator/backendopt: . test Message-ID: <20060506141558.01BDE10083@code0.codespeak.net> Author: cfbolz Date: Sat May 6 16:15:57 2006 New Revision: 26875 Modified: pypy/dist/pypy/translator/backendopt/propagate.py pypy/dist/pypy/translator/backendopt/test/test_propagate.py Log: move check that certain getsubstructs are not folded into op_dont_fold. rename wrongly named test Modified: pypy/dist/pypy/translator/backendopt/propagate.py ============================================================================== --- pypy/dist/pypy/translator/backendopt/propagate.py (original) +++ pypy/dist/pypy/translator/backendopt/propagate.py Sat May 6 16:15:57 2006 @@ -138,6 +138,12 @@ CONTAINER = op.args[0].concretetype.TO if CONTAINER._hints.get('immutable'): return False + if op.opname in ("getsubstruct", "getarraysubstruct"): + # this is needed so that the parent of the result (op.args[0]) + # does not go away after the op is folded. see test_dont_fold_getsubstruct + if not var_needsgc(op.result): + return True + # XXX if the result is immortal, one could still fold... try: return not lloperation.LL_OPERATIONS[op.opname].canfold except KeyError: @@ -153,10 +159,6 @@ if sum([isinstance(arg, Variable) for arg in op.args]): continue if not op_dont_fold(op): - if op.opname in ("getsubstruct", "getarraysubstruct"): - # XXX why this case? - if not var_needsgc(op.result): - continue try: llframe.eval_operation(op) except: Modified: pypy/dist/pypy/translator/backendopt/test/test_propagate.py ============================================================================== --- pypy/dist/pypy/translator/backendopt/test/test_propagate.py (original) +++ pypy/dist/pypy/translator/backendopt/test/test_propagate.py Sat May 6 16:15:57 2006 @@ -155,7 +155,7 @@ pass check_graph(graph, [10], 10, t) -def test_dont_fold_getfield(): +def test_dont_fold_getsubstruct(): # must not constant fold this, because the container might be collected string = "blablabla" def f(x): From arigo at codespeak.net Sat May 6 17:16:26 2006 From: arigo at codespeak.net (arigo at codespeak.net) Date: Sat, 6 May 2006 17:16:26 +0200 (CEST) Subject: [pypy-svn] r26876 - pypy/dist/pypy/doc Message-ID: <20060506151626.5F15910083@code0.codespeak.net> Author: arigo Date: Sat May 6 17:16:25 2006 New Revision: 26876 Modified: pypy/dist/pypy/doc/independent-project-ideas.txt Log: Updated the SoC project ideas with the warning posted to pypy-dev. Modified: pypy/dist/pypy/doc/independent-project-ideas.txt ============================================================================== --- pypy/dist/pypy/doc/independent-project-ideas.txt (original) +++ pypy/dist/pypy/doc/independent-project-ideas.txt Sat May 6 17:16:25 2006 @@ -8,6 +8,16 @@ (This might not actually be true, if you want to finish it all; two months should get some major sub-goals done.) +:: + + Note about the Summer of Code: Your proposals need to somehow + give the impression that they are yours, and that your are interested in + them and have some idea about what is involved. Feel free to discuss + ideas on pypy-dev, and submit proposals early -- you'll get early feedback + from us too, and you can update your proposal any number of times until the + deadline. Basically, just copy-and-pasting one of the paragraphs from + here is *not* enough for a proposal! + In no particular order: * Rewrite one or several CPython extension modules to be based on **ctypes** From arigo at codespeak.net Sat May 6 19:23:49 2006 From: arigo at codespeak.net (arigo at codespeak.net) Date: Sat, 6 May 2006 19:23:49 +0200 (CEST) Subject: [pypy-svn] r26881 - in pypy/dist/pypy: annotation rpython rpython/test Message-ID: <20060506172349.0438C10083@code0.codespeak.net> Author: arigo Date: Sat May 6 19:23:48 2006 New Revision: 26881 Modified: pypy/dist/pypy/annotation/builtin.py pypy/dist/pypy/rpython/rbuiltin.py pypy/dist/pypy/rpython/test/test_rptr.py Log: Support for Ptr() calls in ll functions. Modified: pypy/dist/pypy/annotation/builtin.py ============================================================================== --- pypy/dist/pypy/annotation/builtin.py (original) +++ pypy/dist/pypy/annotation/builtin.py Sat May 6 19:23:48 2006 @@ -455,6 +455,10 @@ 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()))) +def constPtr(T): + assert T.is_constant() + return immutablevalue(lltype.Ptr(T.const)) + BUILTIN_ANALYZERS[lltype.malloc] = malloc BUILTIN_ANALYZERS[lltype.typeOf] = typeOf BUILTIN_ANALYZERS[lltype.cast_primitive] = cast_primitive @@ -467,6 +471,7 @@ BUILTIN_ANALYZERS[lltype.cast_int_to_ptr] = cast_int_to_ptr BUILTIN_ANALYZERS[lltype.getRuntimeTypeInfo] = getRuntimeTypeInfo BUILTIN_ANALYZERS[lltype.runtime_type_info] = runtime_type_info +BUILTIN_ANALYZERS[lltype.Ptr] = constPtr # ootype from pypy.annotation.model import SomeOOInstance, SomeOOClass Modified: pypy/dist/pypy/rpython/rbuiltin.py ============================================================================== --- pypy/dist/pypy/rpython/rbuiltin.py (original) +++ pypy/dist/pypy/rpython/rbuiltin.py Sat May 6 19:23:48 2006 @@ -404,6 +404,7 @@ BUILTIN_TYPER[lltype.typeOf] = rtype_const_result BUILTIN_TYPER[lltype.nullptr] = rtype_const_result BUILTIN_TYPER[lltype.getRuntimeTypeInfo] = rtype_const_result +BUILTIN_TYPER[lltype.Ptr] = 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 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 Sat May 6 19:23:48 2006 @@ -109,3 +109,12 @@ assert s == cast_pointer(PS, t) interpret(fn, [11521]) + + +def test_Ptr(): + S = GcStruct('s') + def ll_example(): + return malloc(Ptr(S).TO) + + p = interpret(ll_example, []) + assert typeOf(p) == Ptr(S) From arigo at codespeak.net Sat May 6 20:23:01 2006 From: arigo at codespeak.net (arigo at codespeak.net) Date: Sat, 6 May 2006 20:23:01 +0200 (CEST) Subject: [pypy-svn] r26885 - in pypy/dist/pypy: rpython translator/stackless translator/stackless/test Message-ID: <20060506182301.101E310083@code0.codespeak.net> Author: arigo Date: Sat May 6 20:22:58 2006 New Revision: 26885 Modified: pypy/dist/pypy/rpython/rbuiltin.py pypy/dist/pypy/translator/stackless/code.py pypy/dist/pypy/translator/stackless/test/test_transform.py pypy/dist/pypy/translator/stackless/test/test_yield_current_frame_to_caller.py pypy/dist/pypy/translator/stackless/transform.py Log: (pedronis, arigo) Pass the yield_current_frame_to_caller() tests. Phew. Modified: pypy/dist/pypy/rpython/rbuiltin.py ============================================================================== --- pypy/dist/pypy/rpython/rbuiltin.py (original) +++ pypy/dist/pypy/rpython/rbuiltin.py Sat May 6 20:22:58 2006 @@ -357,21 +357,46 @@ def rtype_cast_primitive(hop): assert hop.args_s[0].is_constant() TGT = hop.args_s[0].const - # we don't want these as automatic conversions, so: - if TGT == lltype.Char: - hop2 = hop.copy() - hop2.r_s_popfirstarg() - return hop2.args_r[0].rtype_chr(hop2) - elif TGT == lltype.UniChar: - hop2 = hop.copy() - hop2.r_s_popfirstarg() - return hop2.args_r[0].rtype_unichr(hop2) - elif hop.args_r[1] in (rstr.char_repr, rstr.unichar_repr): - hop2 = hop.copy() - hop2.r_s_popfirstarg() - v = hop2.args_r[0].rtype_ord(hop2) - return hop.llops.convertvar(v, rint.signed_repr, hop.r_result) - return hop.inputarg(TGT, 1) + v_type, v_value = hop.inputargs(lltype.Void, hop.args_r[1]) + return gen_cast(hop.llops, TGT, v_value) + +_cast_to_Signed = { + lltype.Signed: None, + lltype.Bool: 'cast_bool_to_int', + lltype.Char: 'cast_char_to_int', + lltype.UniChar: 'cast_unichar_to_int', + lltype.Float: 'cast_float_to_int', + lltype.Unsigned: 'cast_uint_to_int', + } +_cast_from_Signed = { + lltype.Signed: None, + lltype.Bool: 'cast_int_to_bool', + lltype.Char: 'cast_int_to_char', + lltype.UniChar: 'cast_int_to_unichar', + lltype.Float: 'cast_int_to_float', + lltype.Unsigned: 'cast_int_to_uint', + } +def gen_cast(llops, TGT, v_value): + ORIG = v_value.concretetype + if ORIG == TGT: + return v_value + if (isinstance(TGT, lltype.Primitive) and + isinstance(ORIG, lltype.Primitive)): + op = _cast_to_Signed[ORIG] + if op: + v_value = llops.genop(op, [v_value], resulttype = lltype.Signed) + op = _cast_from_Signed[TGT] + if op: + v_value = llops.genop(op, [v_value], resulttype = TGT) + return v_value + elif isinstance(TGT, lltype.Ptr): + if isinstance(ORIG, lltype.Ptr): + return llops.genop('cast_pointer', [v_value], resulttype = TGT) + elif ORIG == llmemory.Address: + return llops.genop('cast_adr_to_ptr', [v_value], resulttype = TGT) + elif TGT == llmemory.Address and isinstance(ORIG, lltype.Ptr): + return llops.genop('cast_ptr_to_adr', [v_value], resulttype = TGT) + raise TypeError("don't know how to cast from %r to %r" % (ORIG, TGT)) def rtype_cast_ptr_to_int(hop): assert isinstance(hop.args_r[0], rptr.PtrRepr) Modified: pypy/dist/pypy/translator/stackless/code.py ============================================================================== --- pypy/dist/pypy/translator/stackless/code.py (original) +++ pypy/dist/pypy/translator/stackless/code.py Sat May 6 20:22:58 2006 @@ -1,66 +1,58 @@ from pypy.rpython.lltypesystem import lltype, llmemory, lloperation from pypy.rpython import rarithmetic + +def ll_frame_switch(state): + if global_state.restart_substate == 0: + u = UnwindException() + s = lltype.malloc(SWITCH_STATE) + s.header.restartstate = 1 + # the next three lines are pure rtyper-pleasing hacks + f = ll_frame_switch + if global_state.restart_substate: + f = None + s.c = llmemory.cast_ptr_to_adr(state) + s.header.function = llmemory.cast_ptr_to_adr(f) + add_frame_state(u, s.header) + raise u + elif global_state.restart_substate == 1: + global_state.restart_substate = 0 + top = global_state.top + s = lltype.cast_pointer(lltype.Ptr(SWITCH_STATE), top) + top.restartstate = 2 + state = llmemory.cast_adr_to_ptr(s.c, lltype.Ptr(STATE_HEADER)) + global_state.top = state + global_state.retval_void_p = llmemory.cast_ptr_to_adr(top) + raise UnwindException() + else: + top = global_state.top + global_state.top = null_state + global_state.restart_substate = 0 + origin_state = llmemory.cast_adr_to_ptr(fetch_retval_void_p(), + lltype.Ptr(STATE_HEADER)) + return origin_state +ll_frame_switch.stackless_explicit = True + STATE_HEADER = lltype.GcStruct('state_header', ('f_back', lltype.Ptr(lltype.GcForwardReference())), ('restartstate', lltype.Signed), ('function', llmemory.Address), - ('retval_type', lltype.Signed)) + ('retval_type', lltype.Signed), + adtmeths={'switch': ll_frame_switch}) STATE_HEADER.f_back.TO.become(STATE_HEADER) null_state = lltype.nullptr(STATE_HEADER) -def decode_state(currentframe): - return (currentframe.function, - currentframe.retval_type, - currentframe.restartstate) -decode_state.stackless_explicit = True +##def decode_state(currentframe): +## return (currentframe.function, +## currentframe.retval_type, +## currentframe.restartstate) +##decode_state.stackless_explicit = True SWITCH_STATE = lltype.GcStruct('state_switch', ('header', STATE_HEADER), ('c', llmemory.Address)) -class Frame(object): - def __init__(self, state): - self.state = state - __init__.stackless_explicit = True - def switch(self): - if global_state.restart_substate == 0: - u = UnwindException() - s = lltype.malloc(SWITCH_STATE) - s.header.restartstate = 1 - # the next three lines are pure rtyper-pleasing hacks - f = Frame.switch - if global_state.restart_substate: - f = None - s.c = llmemory.cast_ptr_to_adr(self.state) - s.header.function = llmemory.cast_ptr_to_adr(f) - add_frame_state(u, s.header) - raise u - elif global_state.restart_substate == 1: - top = global_state.top - state = lltype.cast_pointer(lltype.Ptr(SWITCH_STATE), top) - u = UnwindException() - s.header.restartstate = 2 - c = lltype.cast_adr_to_ptr(lltype.Ptr(STATE_HEADER), top) - s.header.function = c.function - s.reader.retval_type = RETVAL_VOID_P - # the next three lines are pure rtyper-pleasing hacks - f = Frame.switch - if global_state.restart_substate: - f = None - add_frame_state(u, s.header) - raise u - else: - top = global_state.top - global_state.restart_substate = 0 - r = top.f_back - state = lltype.cast_pointer(lltype.Ptr(SWITCH_STATE), top) - global_state.top = lltype.cast_adr_to_ptr(lltype.Ptr(STATE_HEADER), state.c) - #global_state.restart_substate = state.header.restartstate - return r - switch.stackless_explicit = True - def yield_current_frame_to_caller(): if global_state.restart_substate == 0: u = UnwindException() @@ -75,25 +67,37 @@ add_frame_state(u, s) raise u elif global_state.restart_substate == 1: + global_state.restart_substate = 0 ycftc_state = global_state.top + ycftc_state.restartstate = 2 our_caller_state = ycftc_state.f_back caller_state = our_caller_state.f_back - cur = caller_state - while cur.f_back: - cur = cur.f_back - bot = cur - u = UnwindException() - u.frame_top = caller_state - u.frame_bottom = bot - global_state.retval_void_p = llmemory.cast_ptr_to_adr(Frame(ycftc_state)) - global_state.restart_substate = 2 - raise u + # the next three lines are pure rtyper-pleasing hacks + f = yield_current_frame_to_caller + if global_state.restart_substate: + f = None + endstate = lltype.malloc(STATE_HEADER) + endstate.restartstate = 3 + endstate.function = llmemory.cast_ptr_to_adr(f) + our_caller_state.f_back = endstate + global_state.top = caller_state + global_state.retval_void_p = llmemory.cast_ptr_to_adr(ycftc_state) + raise UnwindException() + elif global_state.restart_substate == 2: + top = global_state.top + global_state.top = null_state + global_state.restart_substate = 0 + origin_state = llmemory.cast_adr_to_ptr(fetch_retval_void_p(), + lltype.Ptr(STATE_HEADER)) + return origin_state else: - pass - - + global_state.restart_substate = 0 + next_state = llmemory.cast_adr_to_ptr(fetch_retval_void_p(), + lltype.Ptr(STATE_HEADER)) + global_state.top = next_state + raise UnwindException() + yield_current_frame_to_caller.stackless_explicit = True - def stack_frames_depth(): if not global_state.restart_substate: @@ -152,44 +156,47 @@ class UnwindException(Exception): def __init__(self): - # frame_top points to frame that first caught the - # UnwindException, whilst frame_bottom points to the frame - # that most recently caught the UnwindException. frame_bottom - # is only needed to efficiently tack frames on to the end of - # the stack. walking frame_top.f_back.f_back... goes to - # frame_bottom - self.frame_top = null_state + # during unwind, global_state.top points to frame that first caught + # the UnwindException, whilst frame_bottom points to the frame + # that most recently caught the UnwindException. In a normal + # situation, frame_bottom is global_state.top.f_back.f_back.etc... + # To switch manually to a different frame, code issues a regular + # UnwindException first, to empty the C stack, and then issues a + # (XXX complete this comment) self.frame_bottom = null_state def slp_main_loop(): """ slp_main_loop() keeps resuming... """ - currentframe = global_state.top + pending = global_state.top - while currentframe: - global_state.top = currentframe - nextframe = currentframe.f_back - fn, signature, global_state.restart_substate = decode_state(currentframe) + while True: + back = pending.f_back + fn = pending.function + signature = pending.retval_type + global_state.restart_substate = pending.restartstate try: call_function(fn, signature) except UnwindException, u: #XXX annotation support needed - u.frame_bottom.f_back = nextframe - nextframe = u.frame_top + if u.frame_bottom: + u.frame_bottom.f_back = back + pending = global_state.top + continue except Exception, e: + if not back: + raise global_state.exception = e else: - global_state.exception = None - - currentframe = nextframe + if not back: + return + global_state.top = pending = back - if global_state.exception is not None: - raise global_state.exception slp_main_loop.stackless_explicit = True def add_frame_state(u, frame_state): - if not u.frame_top: - u.frame_top = u.frame_bottom = frame_state + if not u.frame_bottom: + global_state.top = u.frame_bottom = frame_state else: u.frame_bottom.f_back = frame_state u.frame_bottom = frame_state @@ -212,34 +219,44 @@ # XXX and then insert the rtyped graph of this into functions def fetch_retval_void(): - if global_state.exception: - raise global_state.exception + e = global_state.exception + if e: + global_state.exception = None + raise e fetch_retval_void.stackless_explicit = True def fetch_retval_long(): - if global_state.exception: - raise global_state.exception + e = global_state.exception + if e: + global_state.exception = None + raise e else: return global_state.retval_long fetch_retval_long.stackless_explicit = True def fetch_retval_longlong(): - if global_state.exception: - raise global_state.exception + e = global_state.exception + if e: + global_state.exception = None + raise e else: return global_state.retval_longlong fetch_retval_longlong.stackless_explicit = True def fetch_retval_float(): - if global_state.exception: - raise global_state.exception + e = global_state.exception + if e: + global_state.exception = None + raise e else: return global_state.retval_float fetch_retval_float.stackless_explicit = True def fetch_retval_void_p(): - if global_state.exception: - raise global_state.exception + e = global_state.exception + if e: + global_state.exception = None + raise e else: return global_state.retval_void_p fetch_retval_void_p.stackless_explicit = True Modified: pypy/dist/pypy/translator/stackless/test/test_transform.py ============================================================================== --- pypy/dist/pypy/translator/stackless/test/test_transform.py (original) +++ pypy/dist/pypy/translator/stackless/test/test_transform.py Sat May 6 20:22:58 2006 @@ -155,8 +155,8 @@ # helpers which can cause slp_main_loop to get re-annotated after # it is rtyped. which is bad. unwind_def = bk.getuniqueclassdef(code.UnwindException) - unwind_def.generalize_attr('frame_top', - annmodel.SomePtr(lltype.Ptr(code.STATE_HEADER))) + #unwind_def.generalize_attr('frame_top', + # annmodel.SomePtr(lltype.Ptr(code.STATE_HEADER))) unwind_def.generalize_attr('frame_bottom', annmodel.SomePtr(lltype.Ptr(code.STATE_HEADER))) @@ -174,7 +174,6 @@ try: r = fn(len(argv)) except code.UnwindException, u: - code.global_state.top = u.frame_top code.slp_main_loop() r = code.global_state.retval_long os.write(1, str(r)+'\n') @@ -197,7 +196,6 @@ try: r = fn(len(argv)) except code.UnwindException, u: - code.global_state.top = u.frame_top code.slp_main_loop() return code.global_state.retval_long return r Modified: pypy/dist/pypy/translator/stackless/test/test_yield_current_frame_to_caller.py ============================================================================== --- pypy/dist/pypy/translator/stackless/test/test_yield_current_frame_to_caller.py (original) +++ pypy/dist/pypy/translator/stackless/test/test_yield_current_frame_to_caller.py Sat May 6 20:22:58 2006 @@ -4,19 +4,30 @@ import py import os -py.test.skip('in progress') +#py.test.skip('in progress') def test_simple(): def f(ignored): c = g() - #c.switch() + return 1 + def g(): + code.yield_current_frame_to_caller() + + data = llinterp_stackless_function(f) + assert data == 1 + + +def test_switch(): + def f(ignored): + c = g() + c.switch() return 1 def g(): d = code.yield_current_frame_to_caller() return d data = llinterp_stackless_function(f) - assert data == 1234567 + assert data == 1 def test_yield_frame(): @@ -37,7 +48,7 @@ lst.append(5) frametop_after_return = frametop_before_6.switch() lst.append(7) - assert frametop_after_return is None + assert bool(frametop_after_return) n = 0 for i in lst: n = n*10 + i Modified: pypy/dist/pypy/translator/stackless/transform.py ============================================================================== --- pypy/dist/pypy/translator/stackless/transform.py (original) +++ pypy/dist/pypy/translator/stackless/transform.py Sat May 6 20:22:58 2006 @@ -9,6 +9,8 @@ from pypy.translator.stackless import code from pypy.rpython.rclass import getinstancerepr from pypy.rpython.typesystem import getfunctionptr +from pypy.rpython.rbuiltin import gen_cast +from pypy.rpython.rtyper import LowLevelOpList from pypy.translator.stackless.code import STATE_HEADER, null_state @@ -47,7 +49,9 @@ # ('saved_long_0', Signed)) # # def func(x): -# if global_state.restart_substate == 0: +# state = global_state.restart_substate +# global_state.restart_substate = 0 +# if state == 0: # normal case # try: # retval = g(x) # except code.UnwindException, u: @@ -58,9 +62,10 @@ # state.saved_long_0 = x # code.add_frame_state(u, state.header) # raise -# elif global_state.restart_substate == 1: +# elif state == 1: # state = lltype.cast_pointer(lltype.Ptr(STATE_func_0), # global_state.top) +# global_state.top = null_state # x = state.saved_long_0 # retval = global_state.long_retval # else: @@ -139,12 +144,10 @@ def frame_type_for_vars(self, vars): types = [storage_type(v.concretetype) for v in vars] - counts = dict.fromkeys(range(len(STORAGE_TYPES)), 0) + counts = [0] * len(STORAGE_TYPES) for t in types: counts[t] = counts[t] + 1 - keys = counts.keys() - keys.sort() - key = tuple([counts[k] for k in keys]) + key = tuple(counts) if key in self.frametypes: return self.frametypes[key] else: @@ -246,8 +249,6 @@ else: rettype = lltype.Void - need_address_conversion = False - if rettype == lltype.Signed: getretval = self.fetch_retval_long_ptr if rettype == lltype.SignedLongLong: @@ -257,21 +258,14 @@ elif rettype == lltype.Float: getretval = self.fetch_retval_float_ptr elif rettype == llmemory.Address: - if resume_point.var_result.concretetype is not \ - llmemory.Address: - if resume_point.var_result in \ - resume_point.links_to_resumption[0].args: - need_address_conversion = True +## if resume_point.var_result.concretetype is not \ +## llmemory.Address: +## if resume_point.var_result in \ +## resume_point.links_to_resumption[0].args: +## need_address_conversion = True getretval = self.fetch_retval_void_p_ptr - - if need_address_conversion: - varmap[resume_point.var_result] = retval = ( - varoftype(llmemory.Address)) - self.translator.annotator.setbinding( - retval, annmodel.SomeAddress()) - else: - varmap[resume_point.var_result] = retval = ( - unsimplify.copyvar(self.translator, resume_point.var_result)) + + varmap[resume_point.var_result] = retval = varoftype(rettype) ops.append(model.SpaceOperation("direct_call", [getretval], retval)) newblock.operations.extend(ops) @@ -296,18 +290,23 @@ else: newblock.exitswitch = None - if need_address_conversion: - newvar = unsimplify.copyvar(self.translator, resume_point.var_result) - newops = [model.SpaceOperation("cast_adr_to_ptr", - [retval], - newvar)] + if resume_point.var_result.concretetype != rettype: + llops = LowLevelOpList(None) + newvar = gen_cast(llops, + resume_point.var_result.concretetype, + retval) convertblock = unsimplify.insert_empty_block( - self.translator, newblock.exits[0], newops) + self.translator, newblock.exits[0], llops) # begin ouch! - index = newblock.exits[0].args.index(retval) - var = convertblock.inputargs[index] - index2 = convertblock.exits[0].args.index(var) - convertblock.exits[0].args[index2] = newvar + for index, linkvar in enumerate(convertblock.exits[0].args): + # does this var come from retval ? + try: + index1 = convertblock.inputargs.index(linkvar) + except IndexError: + continue + if newblock.exits[0].args[index1] is retval: + # yes + convertblock.exits[0].args[index] = newvar # end ouch! resuming_links.append( @@ -347,11 +346,12 @@ # which doesn't preserve the annotation. so put it back # here. it certainly sucks that this module has to worry # about annotations :( - ann = self.translator.annotator - for f, t in zip(link.args, link.target.inputargs): - nb = ann.binding(f, None) - if nb is not None: - ann.setbinding(t, nb) +## XXX is this still needed? +## ann = self.translator.annotator +## for f, t in zip(link.args, link.target.inputargs): +## nb = ann.binding(f, None) +## if nb is not None: +## ann.setbinding(t, nb) block.exitswitch = model.c_last_exception link.llexitcase = None var_unwind_exception = varoftype(evalue) From arigo at codespeak.net Sat May 6 20:34:53 2006 From: arigo at codespeak.net (arigo at codespeak.net) Date: Sat, 6 May 2006 20:34:53 +0200 (CEST) Subject: [pypy-svn] r26890 - pypy/dist/pypy/interpreter Message-ID: <20060506183453.A885010083@code0.codespeak.net> Author: arigo Date: Sat May 6 20:34:52 2006 New Revision: 26890 Modified: pypy/dist/pypy/interpreter/pycompiler.py Log: (pedronis, arigo) Fix strange except:. (thanks fijal) Modified: pypy/dist/pypy/interpreter/pycompiler.py ============================================================================== --- pypy/dist/pypy/interpreter/pycompiler.py (original) +++ pypy/dist/pypy/interpreter/pycompiler.py Sat May 6 20:34:52 2006 @@ -238,11 +238,8 @@ except SyntaxError, e: raise OperationError(space.w_SyntaxError, e.wrap_info(space, filename)) - except ValueError,e: - raise OperationError(space.w_ValueError,space.wrap(str(e))) - except TypeError,e: - raise - raise OperationError(space.w_TypeError,space.wrap(str(e))) + except (ValueError, TypeError), e: + raise OperationError(space.w_SystemError, space.wrap(str(e))) assert isinstance(c,PyCode) return c From arigo at codespeak.net Sat May 6 20:57:00 2006 From: arigo at codespeak.net (arigo at codespeak.net) Date: Sat, 6 May 2006 20:57:00 +0200 (CEST) Subject: [pypy-svn] r26895 - in pypy/dist/pypy: rpython translator/stackless Message-ID: <20060506185700.76A8B10083@code0.codespeak.net> Author: arigo Date: Sat May 6 20:56:58 2006 New Revision: 26895 Modified: pypy/dist/pypy/rpython/rtyper.py pypy/dist/pypy/translator/stackless/transform.py Log: (pedronis, arigo) Type-erase the frame state structures. Modified: pypy/dist/pypy/rpython/rtyper.py ============================================================================== --- pypy/dist/pypy/rpython/rtyper.py (original) +++ pypy/dist/pypy/rpython/rtyper.py Sat May 6 20:56:58 2006 @@ -759,7 +759,7 @@ llop_raising_exceptions = None implicit_exceptions_checked = None - def __init__(self, rtyper, originalblock=None): + def __init__(self, rtyper=None, originalblock=None): self.rtyper = rtyper self.originalblock = originalblock Modified: pypy/dist/pypy/translator/stackless/transform.py ============================================================================== --- pypy/dist/pypy/translator/stackless/transform.py (original) +++ pypy/dist/pypy/translator/stackless/transform.py Sat May 6 20:56:58 2006 @@ -73,11 +73,13 @@ # return retval + x + 1 class ResumePoint: - def __init__(self, var_result, args, links_to_resumption, frame_state_type): + def __init__(self, var_result, args, links_to_resumption, + frame_state_type, fieldnames): self.var_result = var_result self.args = args self.links_to_resumption = links_to_resumption self.frame_state_type = frame_state_type + self.fieldnames = fieldnames class StacklessTransformer(object): def __init__(self, translator): @@ -143,24 +145,30 @@ def frame_type_for_vars(self, vars): - types = [storage_type(v.concretetype) for v in vars] + fieldnames = [] counts = [0] * len(STORAGE_TYPES) - for t in types: - counts[t] = counts[t] + 1 + for v in vars: + t = storage_type(v.concretetype) + if t is None: + fieldnames.append(None) + else: + fieldnames.append('state_%s_%d' % (STORAGE_FIELDS[t], + counts[t])) + counts[t] = counts[t] + 1 key = tuple(counts) if key in self.frametypes: - return self.frametypes[key] + T = self.frametypes[key] else: fields = [] - for i, k in enumerate(key): - for j in range(k): - fields.append( - ('state_%s_%d'%(STORAGE_FIELDS[i], j), STORAGE_TYPES[i])) - T = lltype.Struct("state_%d_%d_%d_%d"%tuple(key), - ('header', STATE_HEADER), - *fields) + for t in range(len(STORAGE_TYPES)): + for j in range(counts[t]): + fields.append(('state_%s_%d'%(STORAGE_FIELDS[t], j), + STORAGE_TYPES[t])) + T = lltype.GcStruct("FrameState_%d_%d_%d_%d" % tuple(key), + ('header', STATE_HEADER), + *fields) self.frametypes[key] = T - return T + return T, fieldnames def transform_all(self): for graph in self.translator.graphs: @@ -225,23 +233,25 @@ for resume_point_index, resume_point in enumerate(self.resume_points): newblock = model.Block([]) newargs = [] - ops = [] + llops = LowLevelOpList() frame_state_type = resume_point.frame_state_type frame_top = varoftype(lltype.Ptr(frame_state_type)) - ops.extend(self.ops_read_global_state_field(frame_top, "top")) - ops.append(model.SpaceOperation( - "setfield", - [self.ll_global_state, - model.Constant("inst_top", lltype.Void), - model.Constant(null_state, lltype.typeOf(null_state))], - varoftype(lltype.Void))) + llops.extend(self.ops_read_global_state_field(frame_top, "top")) + llops.genop("setfield", + [self.ll_global_state, + model.Constant("inst_top", lltype.Void), + model.Constant(null_state, lltype.typeOf(null_state))]) varmap = {} for i, arg in enumerate(resume_point.args): - newarg = varmap[arg] = unsimplify.copyvar(self.translator, arg) assert arg is not resume_point.var_result - fname = model.Constant(frame_state_type._names[i+1], lltype.Void) - ops.append(model.SpaceOperation( - 'getfield', [frame_top, fname], newarg)) + t = storage_type(arg.concretetype) + if t is None: + continue + fname = model.Constant(resume_point.fieldnames[i], lltype.Void) + v_newarg = llops.genop('getfield', [frame_top, fname], + resulttype = STORAGE_TYPES[t]) + v_newarg = gen_cast(llops, arg.concretetype, v_newarg) + varmap[arg] = v_newarg r = storage_type(resume_point.var_result.concretetype) if r is not None: @@ -265,10 +275,11 @@ ## need_address_conversion = True getretval = self.fetch_retval_void_p_ptr - varmap[resume_point.var_result] = retval = varoftype(rettype) - ops.append(model.SpaceOperation("direct_call", [getretval], retval)) + retval = llops.genop("direct_call", [getretval], + resulttype = rettype) + varmap[resume_point.var_result] = retval - newblock.operations.extend(ops) + newblock.operations.extend(llops) def rename(arg): if isinstance(arg, model.Variable): @@ -291,7 +302,7 @@ newblock.exitswitch = None if resume_point.var_result.concretetype != rettype: - llops = LowLevelOpList(None) + llops = LowLevelOpList() newvar = gen_cast(llops, resume_point.var_result.concretetype, retval) @@ -378,11 +389,12 @@ and arg not in args: args.append(arg) - save_block, frame_state_type = self.generate_save_block( - args, var_unwind_exception) + save_block, frame_state_type, fieldnames = \ + self.generate_save_block(args, var_unwind_exception) self.resume_points.append( - ResumePoint(op.result, args, tuple(block.exits), frame_state_type)) + ResumePoint(op.result, args, tuple(block.exits), + frame_state_type, fieldnames)) newlink = model.Link(args + [var_unwind_exception], save_block, code.UnwindException) @@ -408,17 +420,7 @@ var_unwind_exception = unsimplify.copyvar( self.translator, var_unwind_exception) - fields = [] - n = [] - for i, v in enumerate(varstosave): - assert v.concretetype is not lltype.Void - fields.append(('field_%d'%(i,), v.concretetype)) - n.append(repr(v.concretetype)) - - frame_type = lltype.GcStruct("S" + '-'.join(n), - ('header', STATE_HEADER), - *fields) - + frame_type, fieldnames = self.frame_type_for_vars(varstosave) save_state_block = model.Block(inputargs + [var_unwind_exception]) saveops = save_state_block.operations @@ -429,7 +431,8 @@ [model.Constant(frame_type, lltype.Void)], frame_state_var)) - saveops.extend(self.generate_saveops(frame_state_var, inputargs)) + saveops.extend(self.generate_saveops(frame_state_var, inputargs, + fieldnames)) var_exc = varoftype(self.unwind_exception_type) saveops.append(model.SpaceOperation( @@ -483,16 +486,16 @@ self.curr_graph.exceptblock)) self.translator.rtyper._convert_link( save_state_block, save_state_block.exits[0]) - return save_state_block, frame_type + return save_state_block, frame_type, fieldnames - def generate_saveops(self, frame_state_var, varstosave): + def generate_saveops(self, frame_state_var, varstosave, fieldnames): frame_type = frame_state_var.concretetype.TO - ops = [] + llops = LowLevelOpList() for i, var in enumerate(varstosave): t = storage_type(var.concretetype) - fname = model.Constant(frame_type._names[i+1], lltype.Void) - ops.append(model.SpaceOperation( - 'setfield', - [frame_state_var, fname, var], - varoftype(lltype.Void))) - return ops + if t is lltype.Void: + continue + fname = model.Constant(fieldnames[i], lltype.Void) + v_typeerased = gen_cast(llops, STORAGE_TYPES[t], var) + llops.genop('setfield', [frame_state_var, fname, v_typeerased]) + return llops From arigo at codespeak.net Sat May 6 21:23:53 2006 From: arigo at codespeak.net (arigo at codespeak.net) Date: Sat, 6 May 2006 21:23:53 +0200 (CEST) Subject: [pypy-svn] r26896 - in pypy/dist/pypy: rpython translator/stackless Message-ID: <20060506192353.12BD910083@code0.codespeak.net> Author: arigo Date: Sat May 6 21:23:51 2006 New Revision: 26896 Modified: pypy/dist/pypy/rpython/annlowlevel.py pypy/dist/pypy/translator/stackless/transform.py Log: (pedronis, arigo) Delayed Pointer Technology. Modified: pypy/dist/pypy/rpython/annlowlevel.py ============================================================================== --- pypy/dist/pypy/rpython/annlowlevel.py (original) +++ pypy/dist/pypy/rpython/annlowlevel.py Sat May 6 21:23:51 2006 @@ -8,6 +8,7 @@ from pypy.annotation.policy import AnnotatorPolicy from pypy.rpython.lltypesystem import lltype from pypy.rpython import extfunctable +from pypy.objspace.flow.model import Constant def not_const(s_obj): # xxx move it somewhere else if s_obj.is_constant(): @@ -117,7 +118,8 @@ self.policy = MixLevelAnnotatorPolicy(rtyper) self.pending = [] # list of (graph, args_s, s_result) self.delayedreprs = [] - self.delayedconsts = [] + self.delayedconsts = [] + self.delayedfuncs = [] def getgraph(self, ll_function, args_s, s_result): # get the graph of the mix-level helper ll_function and prepare it for @@ -132,6 +134,19 @@ self.pending.append((graph, args_s, s_result)) return graph + def delayedfunction(self, ll_function, args_s, s_result): + # get a delayed pointer to the low-level function, annotated as + # specified. The pointer is only valid after finish() was called. + graph = self.getgraph(ll_function, args_s, s_result) + FUNCTYPE = lltype.ForwardReference() + delayedptr = lltype._ptr(lltype.Ptr(FUNCTYPE), "delayed!", solid=True) + self.delayedfuncs.append((delayedptr, graph)) + return delayedptr + + def constfunc(self, ll_function, args_s, s_result): + p = self.delayedfunction(ll_function, args_s, s_result) + return Constant(p, lltype.typeOf(p)) + def getdelayedrepr(self, s_value): """Like rtyper.getrepr(), but the resulting repr will not be setup() at all before finish() is called. @@ -180,6 +195,10 @@ r.set_setup_delayed(False) for p, repr, obj in self.delayedconsts: p._become(repr.convert_const(obj)) + for p, graph in self.delayedfuncs: + real_p = rtyper.getcallable(graph) + lltype.typeOf(p).TO.become(lltype.typeOf(real_p).TO) + p._become(real_p) rtyper.specialize_more_blocks() del self.pending[:] del self.delayedreprs[:] Modified: pypy/dist/pypy/translator/stackless/transform.py ============================================================================== --- pypy/dist/pypy/translator/stackless/transform.py (original) +++ pypy/dist/pypy/translator/stackless/transform.py Sat May 6 21:23:51 2006 @@ -8,7 +8,6 @@ from pypy.rpython.annlowlevel import MixLevelHelperAnnotator from pypy.translator.stackless import code from pypy.rpython.rclass import getinstancerepr -from pypy.rpython.typesystem import getfunctionptr from pypy.rpython.rbuiltin import gen_cast from pypy.rpython.rtyper import LowLevelOpList @@ -98,44 +97,28 @@ l2a = annmodel.lltype_to_annotation unwinddef = bk.getuniqueclassdef(code.UnwindException) - add_frame_state_graph = mixlevelannotator.getgraph( + self.add_frame_state_ptr = mixlevelannotator.constfunc( code.add_frame_state, [annmodel.SomeInstance(unwinddef), annmodel.SomePtr(lltype.Ptr(STATE_HEADER))], l2a(lltype.Void)) - resume_state_graph = mixlevelannotator.getgraph( + self.resume_state_ptr = mixlevelannotator.constfunc( code.resume_state, [], annmodel.SomeInteger()) - fetch_retval_void_graph = mixlevelannotator.getgraph( + self.fetch_retval_void_ptr = mixlevelannotator.constfunc( code.fetch_retval_void, [], annmodel.s_None) - fetch_retval_long_graph = mixlevelannotator.getgraph( + self.fetch_retval_long_ptr = mixlevelannotator.constfunc( code.fetch_retval_long, [], annmodel.SomeInteger()) - fetch_retval_longlong_graph = mixlevelannotator.getgraph( # WAA! + self.fetch_retval_longlong_ptr = mixlevelannotator.constfunc( code.fetch_retval_longlong, [], annmodel.SomeInteger(size=2)) - fetch_retval_float_graph = mixlevelannotator.getgraph( + self.fetch_retval_float_ptr = mixlevelannotator.constfunc( code.fetch_retval_float, [], annmodel.SomeFloat()) - fetch_retval_void_p_graph = mixlevelannotator.getgraph( + self.fetch_retval_void_p_ptr = mixlevelannotator.constfunc( code.fetch_retval_void_p, [], annmodel.SomeAddress()) mixlevelannotator.finish() - def fptr(graph): - FTYPE = lltype.FuncType( - [v.concretetype for v in graph.startblock.inputargs], - graph.returnblock.inputargs[0].concretetype) - return model.Constant(getfunctionptr(graph), lltype.Ptr(FTYPE)) - - self.add_frame_state_ptr = fptr(add_frame_state_graph) - - self.resume_state_ptr = fptr(resume_state_graph) - - self.fetch_retval_void_ptr = fptr(fetch_retval_void_graph) - self.fetch_retval_long_ptr = fptr(fetch_retval_long_graph) - self.fetch_retval_longlong_ptr = fptr(fetch_retval_longlong_graph) - self.fetch_retval_float_ptr = fptr(fetch_retval_float_graph) - self.fetch_retval_void_p_ptr = fptr(fetch_retval_void_p_graph) - s_global_state = bk.immutablevalue(code.global_state) r_global_state = translator.rtyper.getrepr(s_global_state) self.ll_global_state = model.Constant( From arigo at codespeak.net Sat May 6 21:35:56 2006 From: arigo at codespeak.net (arigo at codespeak.net) Date: Sat, 6 May 2006 21:35:56 +0200 (CEST) Subject: [pypy-svn] r26897 - pypy/dist/pypy/rpython/lltypesystem/test Message-ID: <20060506193556.DADCE10085@code0.codespeak.net> Author: arigo Date: Sat May 6 21:35:56 2006 New Revision: 26897 Modified: pypy/dist/pypy/rpython/lltypesystem/test/test_rtagged.py Log: Intermediate check-in: run this test with --view, then in the last (3rd) time the pygame viewer shows up, search for the indirect_call in the last block of the entry point function. It should eventually be "constant-folded" into a direct_call in one of the two incoming links. Modified: pypy/dist/pypy/rpython/lltypesystem/test/test_rtagged.py ============================================================================== --- pypy/dist/pypy/rpython/lltypesystem/test/test_rtagged.py (original) +++ pypy/dist/pypy/rpython/lltypesystem/test/test_rtagged.py Sat May 6 21:35:56 2006 @@ -1,7 +1,9 @@ import sys -from pypy.rpython.test.test_llinterp import interpret +from pypy.rpython.test.test_llinterp import interpret, get_interpreter from pypy.rpython.lltypesystem import lltype from pypy.rpython.objectmodel import UnboxedValue +from pypy.translator.backendopt.all import backend_optimizations +from pypy import conftest class A(object): @@ -150,3 +152,17 @@ assert res == 1102 res = interpret(fn, [-1000]) assert res == -897 + +def test_optimize_method(): + def fn(n): + if n > 0: + x = B(n) + else: + x = C(n) + return x.meth(100) + interp, graph = get_interpreter(fn, [1000]) + t = interp.typer.annotator.translator + backend_optimizations(t, propagate=True) + if conftest.option.view: + t.view() + # XXX finish writing this test From arigo at codespeak.net Sat May 6 21:39:05 2006 From: arigo at codespeak.net (arigo at codespeak.net) Date: Sat, 6 May 2006 21:39:05 +0200 (CEST) Subject: [pypy-svn] r26898 - in pypy/dist/pypy: annotation rpython/test Message-ID: <20060506193905.A01FD10085@code0.codespeak.net> Author: arigo Date: Sat May 6 21:39:04 2006 New Revision: 26898 Modified: pypy/dist/pypy/annotation/description.py pypy/dist/pypy/rpython/test/test_rpbc.py Log: Test and fix for manipulating functions that are not actually called anywhere. This used to work but was not directly tested, so I broke it. Modified: pypy/dist/pypy/annotation/description.py ============================================================================== --- pypy/dist/pypy/annotation/description.py (original) +++ pypy/dist/pypy/annotation/description.py Sat May 6 21:39:04 2006 @@ -145,6 +145,11 @@ changed = changed or changed1 return changed + def queryattrfamily(self): + # no attributes supported by default; + # overriden in FrozenDesc and ClassDesc + return None + def bind_under(self, classdef, name): return self 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 May 6 21:39:04 2006 @@ -1247,6 +1247,21 @@ res = interpret(f, [i]) assert res == f(i) + def test_function_as_frozen_pbc(self): + def f1(): pass + def f2(): pass + def choose(n): + if n == 1: + return f1 + else: + return f2 + def f(n): + return choose(n) is f1 + res = interpret(f, [1], type_system=self.ts) + assert res == True + res = interpret(f, [2], type_system=self.ts) + assert res == False + def test_call_from_list(): # Don't test with ootype, since it doesn't support lists in a From arigo at codespeak.net Sat May 6 22:12:24 2006 From: arigo at codespeak.net (arigo at codespeak.net) Date: Sat, 6 May 2006 22:12:24 +0200 (CEST) Subject: [pypy-svn] r26899 - pypy/dist/pypy/translator/stackless/test Message-ID: <20060506201224.1C57610080@code0.codespeak.net> Author: arigo Date: Sat May 6 22:12:22 2006 New Revision: 26899 Modified: pypy/dist/pypy/translator/stackless/test/test_transform.py Log: (pedronis, arigo) Fix and test -- both in the same file :-) Modified: pypy/dist/pypy/translator/stackless/test/test_transform.py ============================================================================== --- pypy/dist/pypy/translator/stackless/test/test_transform.py (original) +++ pypy/dist/pypy/translator/stackless/test/test_transform.py Sat May 6 22:12:22 2006 @@ -34,6 +34,12 @@ from pypy.translator.stackless import code +def test_nothing(): + def fn(ignored): + return 21 + res = llinterp_stackless_function(fn) + assert res == 21 + def test_simple_transform_llinterp(): def check(x): if x: @@ -155,11 +161,11 @@ # helpers which can cause slp_main_loop to get re-annotated after # it is rtyped. which is bad. unwind_def = bk.getuniqueclassdef(code.UnwindException) - #unwind_def.generalize_attr('frame_top', - # annmodel.SomePtr(lltype.Ptr(code.STATE_HEADER))) unwind_def.generalize_attr('frame_bottom', annmodel.SomePtr(lltype.Ptr(code.STATE_HEADER))) - + attrdef = unwind_def.attrs['frame_bottom'] + attrdef.readonly = False + s_returnvar = annotator.build_types(fn, [s_list_of_strings]) if not isinstance(s_returnvar, annmodel.SomeInteger): raise Exception, "this probably isn't going to work" From arigo at codespeak.net Sat May 6 22:50:06 2006 From: arigo at codespeak.net (arigo at codespeak.net) Date: Sat, 6 May 2006 22:50:06 +0200 (CEST) Subject: [pypy-svn] r26901 - in pypy/dist/pypy: rpython translator/stackless translator/stackless/test Message-ID: <20060506205006.B681F10080@code0.codespeak.net> Author: arigo Date: Sat May 6 22:50:05 2006 New Revision: 26901 Modified: pypy/dist/pypy/rpython/annlowlevel.py pypy/dist/pypy/translator/stackless/test/test_depth.py pypy/dist/pypy/translator/stackless/transform.py Log: (pedronis, arigo) Start supporting programs that use the native rpython.rstack interface instead of their code.*() equivalents. Modified: pypy/dist/pypy/rpython/annlowlevel.py ============================================================================== --- pypy/dist/pypy/rpython/annlowlevel.py (original) +++ pypy/dist/pypy/rpython/annlowlevel.py Sat May 6 22:50:05 2006 @@ -116,7 +116,7 @@ def __init__(self, rtyper): self.rtyper = rtyper self.policy = MixLevelAnnotatorPolicy(rtyper) - self.pending = [] # list of (graph, args_s, s_result) + self.pending = [] # list of (ll_function, graph, args_s, s_result) self.delayedreprs = [] self.delayedconsts = [] self.delayedfuncs = [] @@ -131,7 +131,7 @@ for v_arg, s_arg in zip(graph.getargs(), args_s): self.rtyper.annotator.setbinding(v_arg, s_arg) self.rtyper.annotator.setbinding(graph.getreturnvar(), s_result) - self.pending.append((graph, args_s, s_result)) + self.pending.append((ll_function, graph, args_s, s_result)) return graph def delayedfunction(self, ll_function, args_s, s_result): @@ -172,15 +172,17 @@ # push all the graphs into the annotator's pending blocks dict at once rtyper = self.rtyper ann = rtyper.annotator - for graph, args_s, s_result in self.pending: + bk = ann.bookkeeper + for ll_function, graph, args_s, s_result in self.pending: # mark the return block as already annotated, because the return var # annotation was forced in getgraph() above. This prevents temporary # less general values reaching the return block from crashing the # annotator (on the assert-that-new-binding-is-not-less-general). ann.annotated[graph.returnblock] = graph - ann.build_graph_types(graph, args_s, complete_now=False) + s_function = bk.immutablevalue(ll_function) + bk.emulate_pbc_call(graph, s_function, args_s) ann.complete_helpers(self.policy) - for graph, args_s, s_result in self.pending: + for ll_function, graph, args_s, s_result in self.pending: s_real_result = ann.binding(graph.getreturnvar()) if s_real_result != s_result: raise Exception("wrong annotation for the result of %r:\n" Modified: pypy/dist/pypy/translator/stackless/test/test_depth.py ============================================================================== --- pypy/dist/pypy/translator/stackless/test/test_depth.py (original) +++ pypy/dist/pypy/translator/stackless/test/test_depth.py Sat May 6 22:50:05 2006 @@ -1,90 +1,100 @@ from pypy.translator.stackless.test.test_transform import \ llinterp_stackless_function, run_stackless_function from pypy.translator.stackless import code +from pypy.rpython import rstack import py import os -def test_simple(): - def g1(): - "just to check Void special cases around the code" - def g2(ignored): - pass - g1() - def f(n): - g1() - if n > 0: - res = f(n-1) - else: - res = code.stack_frames_depth() - g2(g1) - return res - - def fn(ignored): - count0 = f(0) - count10 = f(10) - return count10 - count0 - - res = llinterp_stackless_function(fn) - assert res == 10 - - res = run_stackless_function(fn) - assert res.strip() == "10" - -def test_with_ptr(): - def f(n): - if n > 0: - res = f(n-1) - else: - res = code.stack_frames_depth(), 1 - return res - - def fn(ignored): - count0, _ = f(0) - count10, _ = f(10) - return count10 - count0 - - res = llinterp_stackless_function(fn) - assert res == 10 - - res = run_stackless_function(fn) - assert res.strip() == "10" - -def test_manytimes(): - def f(n): - if n > 0: - res = f(n-1) - else: - res = code.stack_frames_depth(), 1 - return res - - def fn(ignored): - count0, _ = f(0) - count10, _ = f(100) - return count10 - count0 - - res = llinterp_stackless_function(fn) - assert res == 100 - - res = run_stackless_function(fn) - assert res.strip() == "100" - -def test_arguments(): - def f(n, d, t): - if n > 0: - res = f(n-1, d, t) - else: - res = code.stack_frames_depth(), d, t - return res - - def fn(ignored): - count0, d, t = f(0, 5.5, (1, 2)) - count10, d, t = f(10, 5.5, (1, 2)) - return count10 - count0 + int(d) - - res = llinterp_stackless_function(fn) - assert res == 15 - - res = run_stackless_function(fn) - assert res.strip() == "15" - +class TestFromCode: + stack_frames_depth = staticmethod(code.stack_frames_depth) + + def _freeze_(self): + return True + + def test_simple(self): + def g1(): + "just to check Void special cases around the code" + def g2(ignored): + pass + g1() + def f(n): + g1() + if n > 0: + res = f(n-1) + else: + res = self.stack_frames_depth() + g2(g1) + return res + + def fn(ignored): + count0 = f(0) + count10 = f(10) + return count10 - count0 + + res = llinterp_stackless_function(fn) + assert res == 10 + + res = run_stackless_function(fn) + assert res.strip() == "10" + + def test_with_ptr(self): + def f(n): + if n > 0: + res = f(n-1) + else: + res = self.stack_frames_depth(), 1 + return res + + def fn(ignored): + count0, _ = f(0) + count10, _ = f(10) + return count10 - count0 + + res = llinterp_stackless_function(fn) + assert res == 10 + + res = run_stackless_function(fn) + assert res.strip() == "10" + + def test_manytimes(self): + def f(n): + if n > 0: + res = f(n-1) + else: + res = self.stack_frames_depth(), 1 + return res + + def fn(ignored): + count0, _ = f(0) + count10, _ = f(100) + return count10 - count0 + + res = llinterp_stackless_function(fn) + assert res == 100 + + res = run_stackless_function(fn) + assert res.strip() == "100" + + def test_arguments(self): + def f(n, d, t): + if n > 0: + res = f(n-1, d, t) + else: + res = self.stack_frames_depth(), d, t + return res + + def fn(ignored): + count0, d, t = f(0, 5.5, (1, 2)) + count10, d, t = f(10, 5.5, (1, 2)) + return count10 - count0 + int(d) + + res = llinterp_stackless_function(fn) + assert res == 15 + + res = run_stackless_function(fn) + assert res.strip() == "15" + + +class TestFromRStack(TestFromCode): + stack_frames_depth = staticmethod(rstack.stack_frames_depth) Modified: pypy/dist/pypy/translator/stackless/transform.py ============================================================================== --- pypy/dist/pypy/translator/stackless/transform.py (original) +++ pypy/dist/pypy/translator/stackless/transform.py Sat May 6 22:50:05 2006 @@ -10,6 +10,7 @@ from pypy.rpython.rclass import getinstancerepr from pypy.rpython.rbuiltin import gen_cast from pypy.rpython.rtyper import LowLevelOpList +from pypy.rpython.module import ll_stackless from pypy.translator.stackless.code import STATE_HEADER, null_state @@ -117,6 +118,14 @@ self.fetch_retval_void_p_ptr = mixlevelannotator.constfunc( code.fetch_retval_void_p, [], annmodel.SomeAddress()) + s_StatePtr = annmodel.SomePtr(lltype.Ptr(code.STATE_HEADER)) + self.stack_frames_depth_ptr = mixlevelannotator.constfunc( + code.stack_frames_depth, [], annmodel.SomeInteger()) +## self.yield_current_frame_to_caller_ptr = mixlevelannotator.constfunc( +## code.yield_current_frame_to_caller, [], s_StatePtr) +## self.ll_frame_switch_ptr = mixlevelannotator.constfunc( +## code.ll_frame_switch, [s_StatePtr], s_StatePtr) + mixlevelannotator.finish() s_global_state = bk.immutablevalue(code.global_state) @@ -323,6 +332,15 @@ while i < len(block.operations): op = block.operations[i] if op.opname in ('direct_call', 'indirect_call'): + # trap calls to stackless-related suggested primitives + if op.opname == 'direct_call': + func = getattr(op.args[0].value._obj, '_callable', None) + if func is ll_stackless.ll_stackless_stack_frames_depth: + op = model.SpaceOperation( + 'direct_call', [self.stack_frames_depth_ptr], + op.result) + block.operations[i] = op + if i == len(block.operations) - 1 \ and block.exitswitch == model.c_last_exception: link = block.exits[0] From cfbolz at codespeak.net Sat May 6 23:18:49 2006 From: cfbolz at codespeak.net (cfbolz at codespeak.net) Date: Sat, 6 May 2006 23:18:49 +0200 (CEST) Subject: [pypy-svn] r26907 - pypy/dist/pypy/translator/backendopt Message-ID: <20060506211849.94FEE10083@code0.codespeak.net> Author: cfbolz Date: Sat May 6 23:18:48 2006 New Revision: 26907 Modified: pypy/dist/pypy/translator/backendopt/propagate.py Log: remove the terrible abuse of has_no_side_effects Modified: pypy/dist/pypy/translator/backendopt/propagate.py ============================================================================== --- pypy/dist/pypy/translator/backendopt/propagate.py (original) +++ pypy/dist/pypy/translator/backendopt/propagate.py Sat May 6 23:18:48 2006 @@ -9,6 +9,7 @@ from pypy.translator.backendopt.inline import OP_WEIGHTS from pypy.translator.backendopt.ssa import DataFlowFamilyBuilder from pypy.translator.backendopt.support import log, var_needsgc +from pypy.translator.backendopt.graphanalyze import GraphAnalyzer def do_atmost(n, f, *args): i = 0 @@ -133,24 +134,29 @@ raise TooManyOperations return super(CountingLLFrame, self).eval_operation(operation) -def op_dont_fold(op): - if op.opname in ('getfield', 'getarrayitem'): - CONTAINER = op.args[0].concretetype.TO - if CONTAINER._hints.get('immutable'): - return False - if op.opname in ("getsubstruct", "getarraysubstruct"): - # this is needed so that the parent of the result (op.args[0]) - # does not go away after the op is folded. see test_dont_fold_getsubstruct - if not var_needsgc(op.result): +class CanfoldAnalyzer(GraphAnalyzer): + def operation_is_true(self, op): + if op.opname in ('getfield', 'getarrayitem'): + CONTAINER = op.args[0].concretetype.TO + if CONTAINER._hints.get('immutable'): + return False + if op.opname in ("getsubstruct", "getarraysubstruct"): + # this is needed so that the parent of the result (op.args[0]) + # does not go away after the op is folded. see test_dont_fold_getsubstruct + if not var_needsgc(op.result): + # if the containing object is immortal, one can still fold: + if isinstance(op.args[0], Constant) and op.args[0].value._solid: + return False + return True + try: + return not lloperation.LL_OPERATIONS[op.opname].canfold + except KeyError: return True - # XXX if the result is immortal, one could still fold... - try: - return not lloperation.LL_OPERATIONS[op.opname].canfold - except KeyError: - return True -def constant_folding(graph, translator): +def constant_folding(graph, translator, analyzer=None): """do constant folding if the arguments of an operations are constants""" + if analyzer is None: + analyzer = CanfoldAnalyzer(translator) lli = LLInterpreter(translator.rtyper) llframe = LLFrame(graph, None, lli) changed = False @@ -158,42 +164,31 @@ for i, op in enumerate(block.operations): if sum([isinstance(arg, Variable) for arg in op.args]): continue - if not op_dont_fold(op): - try: - llframe.eval_operation(op) - except: - pass - else: - res = Constant(llframe.getval(op.result)) - log.constantfolding("in graph %s, %s = %s" % - (graph.name, op, res)) - res.concretetype = op.result.concretetype - block.operations[i].opname = "same_as" - block.operations[i].args = [res] - changed = True - elif op.opname == "direct_call": - called_graph = get_graph(op.args[0], translator) - if (called_graph is not None and - simplify.has_no_side_effects( - translator, called_graph, - is_operation_false=op_dont_fold) and - (block.exitswitch != c_last_exception or - i != len(block.operations) - 1)): + # don't fold stuff with exception handling + if (block.exitswitch == c_last_exception and + i == len(block.operation) - 1): + continue + if analyzer.analyze(op): + continue + try: + if op.opname == "direct_call": + called_graph = get_graph(op.args[0], translator) args = [arg.value for arg in op.args[1:]] countingframe = CountingLLFrame(called_graph, args, lli) - #print "folding call", op, "in graph", graph.name - try: - res = countingframe.eval() - except: - #print "did not work" - pass - else: - #print "result", res - res = Constant(res) - res.concretetype = op.result.concretetype - block.operations[i].opname = "same_as" - block.operations[i].args = [res] - changed = True + res = Constant(countingframe.eval()) + else: + llframe.eval_operation(op) + res = Constant(llframe.getval(op.result)) + except (SystemExit, KeyboardInterrupt): + raise + except: + continue + log.constantfolding("in graph %s, %s = %s" % + (graph.name, op, res)) + res.concretetype = op.result.concretetype + block.operations[i].opname = "same_as" + block.operations[i].args = [res] + changed = True block.operations = [op for op in block.operations if op is not None] if changed: remove_same_as(graph) @@ -202,7 +197,9 @@ return True return False -def partial_folding_once(graph, translator): +def partial_folding_once(graph, translator, analyzer=None): + if analyzer is None: + analyzer = CanfoldAnalyzer(translator) lli = LLInterpreter(translator.rtyper) entrymap = mkentrymap(graph) def visit(block): @@ -211,7 +208,7 @@ return usedvars = {} for op in block.operations: - if op_dont_fold(op): + if analyzer.analyze(op): return for arg in op.args: if (isinstance(arg, Variable) and arg in block.inputargs): @@ -249,8 +246,6 @@ else: assert 0, "this should not occur" unchanged = link.target == nextblock and link.args == newargs -# if not unchanged: -# print "doing partial folding in graph", graph.name link.target = nextblock link.args = newargs checkgraph(graph) @@ -365,13 +360,14 @@ def propagate_all_per_graph(graph, translator): def prop(): + analyzer = CanfoldAnalyzer(translator) changed = False changed = rewire_links(graph) or changed changed = propagate_consts(graph) or changed # changed = coalesce_links(graph) or changed # changed = do_atmost(100, constant_folding, graph, -# translator) or changed -# changed = partial_folding(graph, translator) or changed +# translator, analyzer) or changed +# changed = partial_folding(graph, translator, analyzer) or changed changed = remove_all_getfields(graph, translator) or changed checkgraph(graph) return changed From cfbolz at codespeak.net Sat May 6 23:35:22 2006 From: cfbolz at codespeak.net (cfbolz at codespeak.net) Date: Sat, 6 May 2006 23:35:22 +0200 (CEST) Subject: [pypy-svn] r26908 - pypy/dist/pypy/translator/backendopt Message-ID: <20060506213522.9281810083@code0.codespeak.net> Author: cfbolz Date: Sat May 6 23:35:21 2006 New Revision: 26908 Modified: pypy/dist/pypy/translator/backendopt/propagate.py Log: remove usage of visit Modified: pypy/dist/pypy/translator/backendopt/propagate.py ============================================================================== --- pypy/dist/pypy/translator/backendopt/propagate.py (original) +++ pypy/dist/pypy/translator/backendopt/propagate.py Sat May 6 23:35:21 2006 @@ -202,17 +202,21 @@ analyzer = CanfoldAnalyzer(translator) lli = LLInterpreter(translator.rtyper) entrymap = mkentrymap(graph) - def visit(block): - if (not isinstance(block, Block) or block is graph.startblock or - block is graph.returnblock or block is graph.exceptblock): - return + for block in graph.iterblocks(): + if (block is graph.startblock or block is graph.returnblock or + block is graph.exceptblock): + continue usedvars = {} + cannotfold = False for op in block.operations: if analyzer.analyze(op): - return + cannotfold = True + break for arg in op.args: if (isinstance(arg, Variable) and arg in block.inputargs): usedvars[arg] = True + if cannotfold: + continue if isinstance(block.exitswitch, Variable): usedvars[block.exitswitch] = True pattern = [arg in usedvars for arg in block.inputargs] @@ -250,13 +254,8 @@ link.args = newargs checkgraph(graph) if not unchanged: - raise ValueError - try: - traverse(visit, graph) - except ValueError: - return True - else: - return False + return True + return False def partial_folding(graph, translator): """this function does constant folding in the following situation: From cfbolz at codespeak.net Sun May 7 09:20:48 2006 From: cfbolz at codespeak.net (cfbolz at codespeak.net) Date: Sun, 7 May 2006 09:20:48 +0200 (CEST) Subject: [pypy-svn] r26917 - pypy/dist/pypy/translator/backendopt Message-ID: <20060507072048.EF17510080@code0.codespeak.net> Author: cfbolz Date: Sun May 7 09:20:46 2006 New Revision: 26917 Modified: pypy/dist/pypy/translator/backendopt/propagate.py pypy/dist/pypy/translator/backendopt/removenoops.py Log: make partial_folding more general (although a bit inefficient). This makes the optimization a bit too good: it now unrolls loops with constants bounds. On the other hand it nicely folds away isinstance calls on tagged ptrs to just a bit comparison. Modified: pypy/dist/pypy/translator/backendopt/propagate.py ============================================================================== --- pypy/dist/pypy/translator/backendopt/propagate.py (original) +++ pypy/dist/pypy/translator/backendopt/propagate.py Sun May 7 09:20:46 2006 @@ -1,10 +1,11 @@ from pypy.objspace.flow.model import Block, Variable, Constant, c_last_exception from pypy.objspace.flow.model import traverse, mkentrymap, checkgraph -from pypy.objspace.flow.model import SpaceOperation +from pypy.objspace.flow.model import SpaceOperation, Link from pypy.rpython.lltypesystem import lltype, lloperation from pypy.rpython.llinterp import LLInterpreter, LLFrame from pypy.translator import simplify from pypy.translator.simplify import get_graph +from pypy.translator.unsimplify import copyvar from pypy.translator.backendopt.removenoops import remove_same_as from pypy.translator.backendopt.inline import OP_WEIGHTS from pypy.translator.backendopt.ssa import DataFlowFamilyBuilder @@ -197,72 +198,140 @@ return True return False +#def partial_folding_once(graph, translator, analyzer=None): +# if analyzer is None: +# analyzer = CanfoldAnalyzer(translator) +# lli = LLInterpreter(translator.rtyper) +# entrymap = mkentrymap(graph) +# for block in graph.iterblocks(): +# if (block is graph.startblock or block is graph.returnblock or +# block is graph.exceptblock): +# continue +# usedvars = {} +# cannotfold = False +# for op in block.operations: +# if analyzer.analyze(op): +# cannotfold = True +# break +# for arg in op.args: +# if (isinstance(arg, Variable) and arg in block.inputargs): +# usedvars[arg] = True +# if cannotfold: +# continue +# if isinstance(block.exitswitch, Variable): +# usedvars[block.exitswitch] = True +# pattern = [arg in usedvars for arg in block.inputargs] +# for link in entrymap[block]: +# s = sum([isinstance(arg, Constant) or not p +# for arg, p in zip(link.args, pattern)]) +# if s != len(link.args): +# continue +# args = [] +# for i, arg in enumerate(link.args): +# if isinstance(arg, Constant): +# args.append(arg.value) +# else: +# assert not pattern[i] +# args.append(arg.concretetype._example()) +# llframe = LLFrame(graph, None, lli) +# llframe.fillvars(block, args) +# nextblock, forwardargs = llframe.eval_block(block) +# if nextblock is not None: +# newargs = [] +# for i, arg in enumerate(nextblock.inputargs): +# try: +# index = [l.target for l in block.exits].index(nextblock) +# index = block.inputargs.index(block.exits[index].args[i]) +# except ValueError: +# c = Constant(forwardargs[i]) +# c.concretetype = arg.concretetype +# newargs.append(c) +# else: +# newargs.append(link.args[index]) +# else: +# assert 0, "this should not occur" +# unchanged = link.target == nextblock and link.args == newargs +# link.target = nextblock +# link.args = newargs +# checkgraph(graph) +# if not unchanged: +# return True +# return False + def partial_folding_once(graph, translator, analyzer=None): + # XXX this is quite a suboptimal way to do it, but was easy to program if analyzer is None: analyzer = CanfoldAnalyzer(translator) lli = LLInterpreter(translator.rtyper) entrymap = mkentrymap(graph) - for block in graph.iterblocks(): - if (block is graph.startblock or block is graph.returnblock or - block is graph.exceptblock): - continue - usedvars = {} - cannotfold = False - for op in block.operations: - if analyzer.analyze(op): - cannotfold = True - break - for arg in op.args: - if (isinstance(arg, Variable) and arg in block.inputargs): - usedvars[arg] = True - if cannotfold: - continue - if isinstance(block.exitswitch, Variable): - usedvars[block.exitswitch] = True - pattern = [arg in usedvars for arg in block.inputargs] - for link in entrymap[block]: - s = sum([isinstance(arg, Constant) or not p - for arg, p in zip(link.args, pattern)]) - if s != len(link.args): - continue - args = [] + for block, links in entrymap.iteritems(): + # identify candidates + for link in links: + available_vars = {} + foldable_ops = {} for i, arg in enumerate(link.args): if isinstance(arg, Constant): - args.append(arg.value) + available_vars[block.inputargs[i]] = True + if not available_vars: + continue + for op in block.operations: + if analyzer.analyze(op): + continue + for arg in op.args: + if not (isinstance(arg, Constant) or arg in available_vars): + break else: - assert not pattern[i] - args.append(arg.concretetype._example()) - llframe = LLFrame(graph, None, lli) - llframe.fillvars(block, args) - nextblock, forwardargs = llframe.eval_block(block) - if nextblock is not None: - newargs = [] - for i, arg in enumerate(nextblock.inputargs): - try: - index = [l.target for l in block.exits].index(nextblock) - index = block.inputargs.index(block.exits[index].args[i]) - except ValueError: - c = Constant(forwardargs[i]) - c.concretetype = arg.concretetype - newargs.append(c) - else: - newargs.append(link.args[index]) - else: - assert 0, "this should not occur" - unchanged = link.target == nextblock and link.args == newargs - link.target = nextblock - link.args = newargs - checkgraph(graph) - if not unchanged: - return True - return False + foldable_ops[op] = True + available_vars[op.result] = True + if not foldable_ops: + continue + # the link is a candidate. copy the target block so that + # constant folding can do its work + # whew, copying is annoying :-(. XXX nicely factor this out + vars_to_newvars = {} + def getnewvar(var): + if var in vars_to_newvars: + return vars_to_newvars[var] + if var is None: + return None + if isinstance(var, Constant): + return var + result = copyvar(translator, var) + vars_to_newvars[var] = result + return result + newops = [] + for op in block.operations: + newargs = [getnewvar(var) for var in op.args] + newresult = getnewvar(op.result) + newops.append(SpaceOperation(op.opname, newargs, newresult)) + newargs = [getnewvar(var) for var in block.inputargs] + newblock = Block(newargs) + newblock.exitswitch = getnewvar(block.exitswitch) + newblock.operations = newops + newlinks = [] + for copylink in block.exits: + newargs = [getnewvar(var) for var in copylink.args] + newlink = Link(newargs, copylink.target, copylink.exitcase) + newlink.prevblock = block + newlink.last_exception = getnewvar(link.last_exception) + newlink.last_exc_value = getnewvar(link.last_exc_value) + if hasattr(link, 'llexitcase'): + newlink.llexitcase = link.llexitcase + newlinks.append(newlink) + newblock.closeblock(*newlinks) + link.target = newblock + propagate_consts(graph) + result = constant_folding(graph, translator, analyzer) + if result: + simplify.join_blocks(graph) + return result -def partial_folding(graph, translator): +def partial_folding(graph, translator, analyzer=None): """this function does constant folding in the following situation: a block has a link that leads to it that has only constant args. Then all the operations of this block are evaluated and the link leading to the block is adjusted according to the resulting value of the exitswitch""" - if do_atmost(1000, partial_folding_once, graph, translator): + if do_atmost(1000, partial_folding_once, graph, translator, analyzer): propagate_consts(graph) simplify.join_blocks(graph) return True @@ -363,10 +432,10 @@ changed = False changed = rewire_links(graph) or changed changed = propagate_consts(graph) or changed -# changed = coalesce_links(graph) or changed -# changed = do_atmost(100, constant_folding, graph, -# translator, analyzer) or changed -# changed = partial_folding(graph, translator, analyzer) or changed + changed = coalesce_links(graph) or changed + changed = do_atmost(100, constant_folding, graph, + translator, analyzer) or changed + changed = partial_folding(graph, translator, analyzer) or changed changed = remove_all_getfields(graph, translator) or changed checkgraph(graph) return changed Modified: pypy/dist/pypy/translator/backendopt/removenoops.py ============================================================================== --- pypy/dist/pypy/translator/backendopt/removenoops.py (original) +++ pypy/dist/pypy/translator/backendopt/removenoops.py Sun May 7 09:20:46 2006 @@ -23,6 +23,9 @@ for i in range(len(op.args)): if op.args[i] == op_result: op.args[i] = op_arg + if op.opname == "indirect_call" and op.args[0] == op_arg: + op.opname = "direct_call" + op.args = op.args[:-1] for link in block.exits: for i in range(len(link.args)): if link.args[i] == op_result: From arigo at codespeak.net Sun May 7 10:25:17 2006 From: arigo at codespeak.net (arigo at codespeak.net) Date: Sun, 7 May 2006 10:25:17 +0200 (CEST) Subject: [pypy-svn] r26918 - in pypy/dist/pypy: annotation rpython rpython/lltypesystem rpython/lltypesystem/test rpython/test Message-ID: <20060507082517.373721007B@code0.codespeak.net> Author: arigo Date: Sun May 7 10:25:14 2006 New Revision: 26918 Modified: pypy/dist/pypy/annotation/builtin.py pypy/dist/pypy/rpython/llinterp.py pypy/dist/pypy/rpython/lltypesystem/lloperation.py pypy/dist/pypy/rpython/lltypesystem/lltype.py pypy/dist/pypy/rpython/lltypesystem/test/test_lltype.py pypy/dist/pypy/rpython/rbuiltin.py pypy/dist/pypy/rpython/test/test_rptr.py Log: (pedronis, arigo) * added GcOpaqueType. * added cast_opaque_ptr to cast between ptr-to-opaque and ptr-to-something-normal. Modified: pypy/dist/pypy/annotation/builtin.py ============================================================================== --- pypy/dist/pypy/annotation/builtin.py (original) +++ pypy/dist/pypy/annotation/builtin.py Sun May 7 10:25:14 2006 @@ -423,6 +423,15 @@ cast_p = lltype.cast_pointer(PtrT.const, s_p.ll_ptrtype._defl()) return SomePtr(ll_ptrtype=lltype.typeOf(cast_p)) +def cast_opaque_ptr(PtrT, s_p): + assert isinstance(s_p, SomePtr), "casting of non-pointer: %r" % s_p + assert PtrT.is_constant() + try: + lltype.cast_opaque_ptr(PtrT.const, s_p.ll_ptrtype._defl()) + except RuntimeError: + pass # the type checks passed, but the _defl opaque cannot be cast + return SomePtr(ll_ptrtype=PtrT.const) + def direct_fieldptr(s_p, s_fieldname): assert isinstance(s_p, SomePtr), "direct_* of non-pointer: %r" % s_p assert s_fieldname.is_constant() @@ -464,6 +473,7 @@ BUILTIN_ANALYZERS[lltype.cast_primitive] = cast_primitive BUILTIN_ANALYZERS[lltype.nullptr] = nullptr BUILTIN_ANALYZERS[lltype.cast_pointer] = cast_pointer +BUILTIN_ANALYZERS[lltype.cast_opaque_ptr] = cast_opaque_ptr BUILTIN_ANALYZERS[lltype.direct_fieldptr] = direct_fieldptr BUILTIN_ANALYZERS[lltype.direct_arrayitems] = direct_arrayitems BUILTIN_ANALYZERS[lltype.direct_ptradd] = direct_ptradd Modified: pypy/dist/pypy/rpython/llinterp.py ============================================================================== --- pypy/dist/pypy/rpython/llinterp.py (original) +++ pypy/dist/pypy/rpython/llinterp.py Sun May 7 10:25:14 2006 @@ -335,7 +335,8 @@ vals = [self.getval(x) for x in operation.args] # if these special cases pile up, do something better here if operation.opname in ['cast_pointer', 'ooupcast', 'oodowncast', - 'cast_adr_to_ptr', 'cast_int_to_ptr']: + 'cast_adr_to_ptr', 'cast_int_to_ptr', + 'cast_opaque_ptr']: vals.insert(0, operation.result.concretetype) try: retval = ophandler(*vals) @@ -556,9 +557,11 @@ return len(array) def op_cast_pointer(self, tp, obj): - # well, actually this is what's now in the globals. return lltype.cast_pointer(tp, obj) + def op_cast_opaque_ptr(self, tp, obj): + return lltype.cast_opaque_ptr(tp, obj) + def op_ptr_eq(self, ptr1, ptr2): assert checkptr(ptr1) assert checkptr(ptr2) Modified: pypy/dist/pypy/rpython/lltypesystem/lloperation.py ============================================================================== --- pypy/dist/pypy/rpython/lltypesystem/lloperation.py (original) +++ pypy/dist/pypy/rpython/lltypesystem/lloperation.py Sun May 7 10:25:14 2006 @@ -270,6 +270,7 @@ 'direct_fieldptr': LLOp(canfold=True), 'direct_arrayitems': LLOp(canfold=True), 'direct_ptradd': LLOp(canfold=True), + 'cast_opaque_ptr': LLOp(canfold=True), # _________ XXX l3interp hacks ___________ Modified: pypy/dist/pypy/rpython/lltypesystem/lltype.py ============================================================================== --- pypy/dist/pypy/rpython/lltypesystem/lltype.py (original) +++ pypy/dist/pypy/rpython/lltypesystem/lltype.py Sun May 7 10:25:14 2006 @@ -427,6 +427,14 @@ RuntimeTypeInfo = OpaqueType("RuntimeTypeInfo") +class GcOpaqueType(OpaqueType): + + def __str__(self): + return "%s (gcopaque)" % self.tag + + def _inline_is_varsize(self, last): + raise TypeError, "%r cannot be inlined in structure" % self + class PyObjectType(ContainerType): __name__ = 'PyObject' def __str__(self): @@ -452,7 +460,8 @@ self.__class__ = realcontainertype.__class__ self.__dict__ = realcontainertype.__dict__ -GC_CONTAINER = (GcStruct, GcArray, PyObjectType, GcForwardReference) +GC_CONTAINER = (GcStruct, GcArray, PyObjectType, GcForwardReference, + GcOpaqueType) class Primitive(LowLevelType): @@ -614,6 +623,33 @@ raise TypeError, "can only cast pointers to other pointers" return ptr._cast_to(PTRTYPE) +def cast_opaque_ptr(PTRTYPE, ptr): + CURTYPE = typeOf(ptr) + if not isinstance(CURTYPE, Ptr) or not isinstance(PTRTYPE, Ptr): + raise TypeError, "can only cast pointers to other pointers" + if CURTYPE._needsgc() != PTRTYPE._needsgc(): + raise TypeError("cast_opaque_ptr() cannot change the gc status: " + "%s to %s" % (CURTYPE, PTRTYPE)) + if (isinstance(CURTYPE.TO, OpaqueType) + and not isinstance(PTRTYPE.TO, OpaqueType)): + try: + container = ptr._obj.container + except AttributeError: + raise RuntimeError("%r does not come from a container" % (ptr,)) + if typeOf(container) != PTRTYPE.TO: + raise RuntimeError("%r contains a container of the wrong type:\n" + "%r instead of %r" % (ptr, typeOf(container), + PTRTYPE.TO)) + solid = getattr(ptr._obj, 'solid', False) + return _ptr(PTRTYPE, container, solid) + elif (not isinstance(CURTYPE.TO, OpaqueType) + and isinstance(PTRTYPE.TO, OpaqueType)): + return opaqueptr(PTRTYPE.TO, 'hidden', container = ptr._obj, + solid = ptr._solid) + else: + raise TypeError("cast_opaque_ptr(): only between Opaque and " + "non-Opaque") + def direct_fieldptr(structptr, fieldname): """Get a pointer to a field in the struct. The resulting pointer is actually of type Ptr(FixedSizeArray(FIELD, 1)). @@ -1264,7 +1300,7 @@ if not isinstance(TYPE, OpaqueType): raise TypeError, "opaqueptr() for OpaqueTypes only" o = _opaque(TYPE, _name=name, **attrs) - return _ptr(Ptr(TYPE), o, solid=attrs.get('immortal', True)) + return _ptr(Ptr(TYPE), o, solid=True) def pyobjectptr(obj): o = _pyobject(obj) Modified: pypy/dist/pypy/rpython/lltypesystem/test/test_lltype.py ============================================================================== --- pypy/dist/pypy/rpython/lltypesystem/test/test_lltype.py (original) +++ pypy/dist/pypy/rpython/lltypesystem/test/test_lltype.py Sun May 7 10:25:14 2006 @@ -430,6 +430,28 @@ assert typeOf(p2.stuff) == Ptr(O) assert parentlink(p2.stuff._obj) == (p2._obj, 'stuff') +def test_cast_opaque_ptr(): + O = GcOpaqueType('O') + S = GcStruct('S', ('x', Signed)) + s = malloc(S) + o = cast_opaque_ptr(Ptr(O), s) + assert typeOf(o).TO == O + p = cast_opaque_ptr(Ptr(S), o) + assert typeOf(p).TO == S + assert p == s + O1 = OpaqueType('O') + S1 = Struct('S1', ('x', Signed)) + s1 = malloc(S1, immortal=True) + o1 = cast_opaque_ptr(Ptr(O1), s1) + assert typeOf(o1).TO == O1 + p1 = cast_opaque_ptr(Ptr(S1), o1) + assert typeOf(p1).TO == S1 + assert p1 == s1 + py.test.raises(TypeError, "cast_opaque_ptr(Ptr(S), o1)") + py.test.raises(TypeError, "cast_opaque_ptr(Ptr(O1), s)") + S2 = Struct('S2', ('z', Signed)) + py.test.raises(TypeError, "cast_opaque_ptr(Ptr(S2), o1)") + def test_is_atomic(): U = Struct('inlined', ('z', Signed)) A = Ptr(RuntimeTypeInfo) Modified: pypy/dist/pypy/rpython/rbuiltin.py ============================================================================== --- pypy/dist/pypy/rpython/rbuiltin.py (original) +++ pypy/dist/pypy/rpython/rbuiltin.py Sun May 7 10:25:14 2006 @@ -332,6 +332,14 @@ return hop.genop('cast_pointer', [v_input], # v_type implicit in r_result resulttype = hop.r_result.lowleveltype) +def rtype_cast_opaque_ptr(hop): + assert hop.args_s[0].is_constant() + assert isinstance(hop.args_r[1], rptr.PtrRepr) + v_type, v_input = hop.inputargs(lltype.Void, hop.args_r[1]) + hop.exception_cannot_occur() + return hop.genop('cast_opaque_ptr', [v_input], # v_type implicit in r_result + resulttype = hop.r_result.lowleveltype) + def rtype_direct_fieldptr(hop): assert isinstance(hop.args_r[0], rptr.PtrRepr) assert hop.args_s[1].is_constant() @@ -421,6 +429,7 @@ BUILTIN_TYPER[lltype.malloc] = rtype_malloc BUILTIN_TYPER[lltype.cast_primitive] = rtype_cast_primitive BUILTIN_TYPER[lltype.cast_pointer] = rtype_cast_pointer +BUILTIN_TYPER[lltype.cast_opaque_ptr] = rtype_cast_opaque_ptr BUILTIN_TYPER[lltype.direct_fieldptr] = rtype_direct_fieldptr BUILTIN_TYPER[lltype.direct_arrayitems] = rtype_direct_arrayitems BUILTIN_TYPER[lltype.direct_ptradd] = rtype_direct_ptradd 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 Sun May 7 10:25:14 2006 @@ -118,3 +118,24 @@ p = interpret(ll_example, []) assert typeOf(p) == Ptr(S) + +def test_cast_opaque_ptr(): + O = GcOpaqueType('O') + S = GcStruct('S', ('x', Signed)) + def fn(): + s = malloc(S) + o = cast_opaque_ptr(Ptr(O), s) + p = cast_opaque_ptr(Ptr(S), o) + return p == s + res = interpret(fn, []) + assert res is True + + O1 = OpaqueType('O') + S1 = Struct('S1', ('x', Signed)) + s1 = malloc(S1, immortal=True) + def fn1(): + o1 = cast_opaque_ptr(Ptr(O1), s1) + p1 = cast_opaque_ptr(Ptr(S1), o1) + return p1 == s1 + res = interpret(fn1, []) + assert res is True From arigo at codespeak.net Sun May 7 10:26:39 2006 From: arigo at codespeak.net (arigo at codespeak.net) Date: Sun, 7 May 2006 10:26:39 +0200 (CEST) Subject: [pypy-svn] r26919 - pypy/dist/pypy/rpython/lltypesystem/test Message-ID: <20060507082639.09B821007B@code0.codespeak.net> Author: arigo Date: Sun May 7 10:26:38 2006 New Revision: 26919 Modified: pypy/dist/pypy/rpython/lltypesystem/test/test_lltype.py Log: Forgot to run all the tests. Modified: pypy/dist/pypy/rpython/lltypesystem/test/test_lltype.py ============================================================================== --- pypy/dist/pypy/rpython/lltypesystem/test/test_lltype.py (original) +++ pypy/dist/pypy/rpython/lltypesystem/test/test_lltype.py Sun May 7 10:26:38 2006 @@ -450,7 +450,7 @@ py.test.raises(TypeError, "cast_opaque_ptr(Ptr(S), o1)") py.test.raises(TypeError, "cast_opaque_ptr(Ptr(O1), s)") S2 = Struct('S2', ('z', Signed)) - py.test.raises(TypeError, "cast_opaque_ptr(Ptr(S2), o1)") + py.test.raises(RuntimeError, "cast_opaque_ptr(Ptr(S2), o1)") def test_is_atomic(): U = Struct('inlined', ('z', Signed)) From cfbolz at codespeak.net Sun May 7 10:48:10 2006 From: cfbolz at codespeak.net (cfbolz at codespeak.net) Date: Sun, 7 May 2006 10:48:10 +0200 (CEST) Subject: [pypy-svn] r26921 - pypy/dist/pypy/translator/backendopt Message-ID: <20060507084810.416E410080@code0.codespeak.net> Author: cfbolz Date: Sun May 7 10:48:08 2006 New Revision: 26921 Modified: pypy/dist/pypy/translator/backendopt/propagate.py Log: typo (and forgot to run test_all :-( Modified: pypy/dist/pypy/translator/backendopt/propagate.py ============================================================================== --- pypy/dist/pypy/translator/backendopt/propagate.py (original) +++ pypy/dist/pypy/translator/backendopt/propagate.py Sun May 7 10:48:08 2006 @@ -313,8 +313,8 @@ newargs = [getnewvar(var) for var in copylink.args] newlink = Link(newargs, copylink.target, copylink.exitcase) newlink.prevblock = block - newlink.last_exception = getnewvar(link.last_exception) - newlink.last_exc_value = getnewvar(link.last_exc_value) + newlink.last_exception = getnewvar(copylink.last_exception) + newlink.last_exc_value = getnewvar(copylink.last_exc_value) if hasattr(link, 'llexitcase'): newlink.llexitcase = link.llexitcase newlinks.append(newlink) From arigo at codespeak.net Sun May 7 10:53:52 2006 From: arigo at codespeak.net (arigo at codespeak.net) Date: Sun, 7 May 2006 10:53:52 +0200 (CEST) Subject: [pypy-svn] r26922 - pypy/dist/pypy/translator/c/test Message-ID: <20060507085352.144441007B@code0.codespeak.net> Author: arigo Date: Sun May 7 10:53:50 2006 New Revision: 26922 Modified: pypy/dist/pypy/translator/c/test/test_newgc.py Log: (pedronis, arigo) Added a passing test checking the basic __del__ support of the framework gc. Modified: pypy/dist/pypy/translator/c/test/test_newgc.py ============================================================================== --- pypy/dist/pypy/translator/c/test/test_newgc.py (original) +++ pypy/dist/pypy/translator/c/test/test_newgc.py Sun May 7 10:53:50 2006 @@ -15,8 +15,9 @@ def compile_func(fn, inputtypes, t=None): if t is None: t = TranslationContext() - t.buildannotator().build_types(fn, inputtypes) - t.buildrtyper().specialize() + if inputtypes is not None: + t.buildannotator().build_types(fn, inputtypes) + t.buildrtyper().specialize() builder = genc.CExtModuleBuilder(t, fn, gcpolicy=gc.RefcountingGcPolicy) builder.generate_source(defines={'COUNT_OP_MALLOCS': 1}) builder.compile() @@ -141,6 +142,34 @@ assert fn(1) == 4 assert fn(0) == 5 +def test_del_basic(): + S = lltype.GcStruct('S', ('x', lltype.Signed)) + lltype.attachRuntimeTypeInfo(S) + GLOBAL = lltype.Struct('GLOBAL', ('x', lltype.Signed)) + glob = lltype.malloc(GLOBAL, immortal=True) + def destructor(s): + glob.x = s.x + 1 + def type_info_S(s): + return lltype.getRuntimeTypeInfo(S) + + def g(n): + s = lltype.malloc(S) + s.x = n + # now 's' should go away + def entrypoint(n): + g(n) + return glob.x + + t = TranslationContext() + t.buildannotator().build_types(entrypoint, [int]) + rtyper = t.buildrtyper() + destrptr = rtyper.annotate_helper_fn(destructor, [lltype.Ptr(S)]) + rtyper.attachRuntimeTypeInfoFunc(S, type_info_S, destrptr=destrptr) + rtyper.specialize() + fn = compile_func(entrypoint, None, t) + + res = fn(123) + assert res == 124 def test_del_catches(): import os From ericvrp at codespeak.net Sun May 7 10:55:59 2006 From: ericvrp at codespeak.net (ericvrp at codespeak.net) Date: Sun, 7 May 2006 10:55:59 +0200 (CEST) Subject: [pypy-svn] r26923 - in pypy/dist/pypy: doc doc/discussion translator/llvm translator/llvm/test Message-ID: <20060507085559.538111007B@code0.codespeak.net> Author: ericvrp Date: Sun May 7 10:55:55 2006 New Revision: 26923 Modified: pypy/dist/pypy/doc/architecture.txt pypy/dist/pypy/doc/cpython-ctypes-behaviour.txt pypy/dist/pypy/doc/dev_method.txt pypy/dist/pypy/doc/discussion/howtoimplementpickling.txt pypy/dist/pypy/doc/dynamic-language-translation.txt pypy/dist/pypy/doc/extradoc.txt pypy/dist/pypy/doc/getting-started.txt pypy/dist/pypy/doc/independent-project-ideas.txt pypy/dist/pypy/doc/translation.txt pypy/dist/pypy/translator/llvm/codewriter.py pypy/dist/pypy/translator/llvm/test/test_typed.py Log: fix of document types + rename url's to llvm website (using llvm.org instead) Modified: pypy/dist/pypy/doc/architecture.txt ============================================================================== --- pypy/dist/pypy/doc/architecture.txt (original) +++ pypy/dist/pypy/doc/architecture.txt Sun May 7 10:55:55 2006 @@ -293,7 +293,7 @@ .. _`abstract interpretation`: theory.html#abstract-interpretation .. _`Compiling dynamic language implementations`: dynamic-language-translation.html .. _`translation document`: translation.html -.. _LLVM: http://llvm.cs.uiuc.edu/ +.. _LLVM: http://llvm.org/ .. _`PDF color version`: image/translation.pdf .. _`getting started`: getting-started.html Modified: pypy/dist/pypy/doc/cpython-ctypes-behaviour.txt ============================================================================== --- pypy/dist/pypy/doc/cpython-ctypes-behaviour.txt (original) +++ pypy/dist/pypy/doc/cpython-ctypes-behaviour.txt Sun May 7 10:55:55 2006 @@ -5,7 +5,7 @@ .. contents:: .. sectnum:: -This documents describes ctypes behaviour on CPython, as fas as it +This documents describes ctypes behaviour on CPython, as far as it is know to the author and relevant for rctypes. Primitive Types @@ -51,7 +51,7 @@ Structures created from foreign pointers ######################################## -The author is currently not shure, whether the text below +The author is currently not sure, whether the text below is correct in all aspects, but carefully planned trials did not provide any evidence to the contrary. @@ -64,9 +64,9 @@ ------------------------------------------- Pointer types are created by a factory function named `POINTER`. -Pointers can be created by either calling and thus istanciating a +Pointers can be created by either calling and thus instanciating a pointer type or by calling another function named `pointer` that -creates the neccessary pointer type on the fly and returns +creates the necessary pointer type on the fly and returns a pointer to the instance. Pointers only implement one attribute named contents which Modified: pypy/dist/pypy/doc/dev_method.txt ============================================================================== --- pypy/dist/pypy/doc/dev_method.txt (original) +++ pypy/dist/pypy/doc/dev_method.txt Sun May 7 10:55:55 2006 @@ -49,7 +49,7 @@ prepares, leads and coordinate the work and track progress and makes this visible for the team. Important to note here - PyPy have never had coaches in our sprints. Instead we hold short status meetings in the whole group, - decisions are made in the same way.So far this have worked well and we + decisions are made in the same way. So far this have worked well and we still have been able to achieve tremendous results under stressed conditions, releases and such like. What we do have is a local organizer, often a developer living in the area and one more developer who prepares @@ -63,13 +63,13 @@ line although again, if you visit a PyPy sprint we are doing quite a lot of other small activities in subgroups as well - planning sprints, documentation, coordinating our EU deliverables and evaluation etc. But - dont worry - our main focus is programming ;-) + don't worry - our main focus is programming ;-) * using XP techniques (mainly pairprogramming and unit testing - PyPy is leaning heavily on these aspects). Pairing up core developers with people with different levels of knowledge of the codebase have had the results that people can quite quickly get started and join in the development. - Many of our particpants (new to the project and the codebased) have + Many of our participants (new to the project and the codebase) have expressed how pairprogramming in combination with working on the automated tests have been a great way of getting started. This is of course also a dilemma because our core developers might have to pair up to solve some Modified: pypy/dist/pypy/doc/discussion/howtoimplementpickling.txt ============================================================================== --- pypy/dist/pypy/doc/discussion/howtoimplementpickling.txt (original) +++ pypy/dist/pypy/doc/discussion/howtoimplementpickling.txt Sun May 7 10:55:55 2006 @@ -46,7 +46,7 @@ Pickling of a running thread involves a bit more than normal object pickling, because there exist many objects which don't have a pickling interface, and people would not care -aboutpickling them at all. But with thread pickling, these +about pickling them at all. But with thread pickling, these objects simply exist as local variables and are needed to restore the current runtime environment, and the user should not have to know what goes into the pickle. @@ -257,7 +257,7 @@ to identify useless activation records in order to support pickling. The remaining, irreducible activation records should then be those which hold a reference to a Python frame. -Such a chain is pickleable iff its root points back to the context switching code +Such a chain is pickleable if its root points back to the context switching code of the interp-level implementation of coroutines. As an observation, this transform not only enables pickling, but @@ -305,7 +305,7 @@ we know that they are held in, for instance, frames. I hope you understand that: If we improve the life-time analysis -of veriables, the sketched problem of above about which blocks +of variables, the sketched problem of above about which blocks need to save state and which don't, should become trivial and should just vanish. Doing this correctly will solve the pickling problem quasi automatically, leading to a more efficient implementation at the same time. Modified: pypy/dist/pypy/doc/dynamic-language-translation.txt ============================================================================== --- pypy/dist/pypy/doc/dynamic-language-translation.txt (original) +++ pypy/dist/pypy/doc/dynamic-language-translation.txt Sun May 7 10:55:55 2006 @@ -2324,7 +2324,7 @@ * Lattice: http://en.wikipedia.org/wiki/Lattice_%28order%29 -* LLVM (Low-Level Virtual Machine): http://llvm.cs.uiuc.edu/ +* LLVM (Low-Level Virtual Machine): http://llvm.org/ * Low-level Types: see [TR]_. @@ -2353,7 +2353,7 @@ .. _`ACM SIGPLAN 2004 paper`: http://psyco.sourceforge.net/psyco-pepm-a.ps.gz .. _`Hindley-Milner`: http://en.wikipedia.org/wiki/Hindley-Milner_type_inference .. _SSA: http://en.wikipedia.org/wiki/Static_single_assignment_form -.. _LLVM: http://llvm.cs.uiuc.edu/ +.. _LLVM: http://llvm.org/ .. _`RTyper reference`: translation.html#rpython-typer .. _`GenC back-end`: translation.html#genc .. _`LLVM back-end`: translation.html#llvm Modified: pypy/dist/pypy/doc/extradoc.txt ============================================================================== --- pypy/dist/pypy/doc/extradoc.txt (original) +++ pypy/dist/pypy/doc/extradoc.txt Sun May 7 10:55:55 2006 @@ -74,7 +74,7 @@ .. _rock: http://codespeak.net/pipermail/pypy-dev/2004q1/001255.html .. _spyweb: http://spyweb.hopto.org/ .. _`GNU lightning`: http://www.gnu.org/software/lightning/lightning.html -.. _LLVM: http://llvm.cs.uiuc.edu/ +.. _LLVM: http://llvm.org/ .. _IronPython: http://www.python.org/pycon/dc2004/papers/9/ .. _`Dynamic Native Optimization of Native Interpreters`: http://www.ai.mit.edu/~gregs/dynamorio.html .. _JikesRVM: http://jikesrvm.sf.net Modified: pypy/dist/pypy/doc/getting-started.txt ============================================================================== --- pypy/dist/pypy/doc/getting-started.txt (original) +++ pypy/dist/pypy/doc/getting-started.txt Sun May 7 10:55:55 2006 @@ -633,10 +633,10 @@ .. _`py library`: http://codespeak.net/py .. _`PyPy/LLVM backend`: translation.html#llvm -.. _`low level virtual machine`: http://llvm.cs.uiuc.edu/ -.. _`how to install LLVM`: http://llvm.cs.uiuc.edu/docs/GettingStarted.html +.. _`low level virtual machine`: http://llvm.org/ +.. _`how to install LLVM`: http://llvm.org/docs/GettingStarted.html .. _`LLVM mailing list`: http://mail.cs.uiuc.edu/mailman/listinfo/llvmdev -.. _`LLVM installed with version 1.6`: http://llvm.cs.uiuc.edu/releases +.. _`LLVM installed with version 1.7`: http://llvm.org/releases .. _Dot Graphviz: http://www.research.att.com/sw/tools/graphviz/ Modified: pypy/dist/pypy/doc/independent-project-ideas.txt ============================================================================== --- pypy/dist/pypy/doc/independent-project-ideas.txt (original) +++ pypy/dist/pypy/doc/independent-project-ideas.txt Sun May 7 10:55:55 2006 @@ -22,7 +22,7 @@ * Rewrite one or several CPython extension modules to be based on **ctypes** (newly integrated in Python 2.5): this is generally useful for Python - developpers, and it is now the best path to write extension modules that are + developers, and it is now the best path to write extension modules that are compatible with both CPython and PyPy. See for example http://wiki.python.org/moin/CodingProjectIdeas/PygameOnCtypes . (This is not documented so far; for an example on which we are working now, Modified: pypy/dist/pypy/doc/translation.txt ============================================================================== --- pypy/dist/pypy/doc/translation.txt (original) +++ pypy/dist/pypy/doc/translation.txt Sun May 7 10:55:55 2006 @@ -1020,7 +1020,7 @@ Heidelberg sprint. During the Heildelberg sprint Eric and Richard mainly worked on sharing the backend external code with GenC. -.. _`low level virtual machine`: http://llvm.cs.uiuc.edu/ +.. _`low level virtual machine`: http://llvm.org/ .. _`here`: getting-started.html#translating-the-flow-graph-to-llvm-code Modified: pypy/dist/pypy/translator/llvm/codewriter.py ============================================================================== --- pypy/dist/pypy/translator/llvm/codewriter.py (original) +++ pypy/dist/pypy/translator/llvm/codewriter.py Sun May 7 10:55:55 2006 @@ -15,7 +15,7 @@ self.file.close() def _resolvetail(self, tail, cconv): - # from: http://llvm.cs.uiuc.edu/docs/LangRef.html + # from: http://llvm.org/docs/LangRef.html # The optional "tail" marker indicates whether the callee function # accesses any allocas or varargs in the caller. If the "tail" marker # is present, the function call is eligible for tail call Modified: pypy/dist/pypy/translator/llvm/test/test_typed.py ============================================================================== --- pypy/dist/pypy/translator/llvm/test/test_typed.py (original) +++ pypy/dist/pypy/translator/llvm/test/test_typed.py Sun May 7 10:55:55 2006 @@ -210,7 +210,7 @@ # floats def test_float_operations(): #llvm rem operation working starting llvm1.6") - #see: http://llvm.cs.uiuc.edu/bugs/show_bug.cgi?id=611 + #see: http://llvm.org/bugs/show_bug.cgi?id=611 import math def func(x, y): z = x + y / 2.1 * x From arigo at codespeak.net Sun May 7 11:06:45 2006 From: arigo at codespeak.net (arigo at codespeak.net) Date: Sun, 7 May 2006 11:06:45 +0200 (CEST) Subject: [pypy-svn] r26924 - pypy/dist/pypy/translator/c/test Message-ID: <20060507090645.F28591007B@code0.codespeak.net> Author: arigo Date: Sun May 7 11:06:45 2006 New Revision: 26924 Modified: pypy/dist/pypy/translator/c/test/test_newgc.py Log: (pedronis, arigo) A third different style of test in the same file. :-( Commented out until the FrameworkGcPolicy has support for destructors. Modified: pypy/dist/pypy/translator/c/test/test_newgc.py ============================================================================== --- pypy/dist/pypy/translator/c/test/test_newgc.py (original) +++ pypy/dist/pypy/translator/c/test/test_newgc.py Sun May 7 11:06:45 2006 @@ -12,13 +12,13 @@ from pypy import conftest -def compile_func(fn, inputtypes, t=None): +def compile_func(fn, inputtypes, t=None, gcpolicy=gc.RefcountingGcPolicy): if t is None: t = TranslationContext() if inputtypes is not None: t.buildannotator().build_types(fn, inputtypes) t.buildrtyper().specialize() - builder = genc.CExtModuleBuilder(t, fn, gcpolicy=gc.RefcountingGcPolicy) + builder = genc.CExtModuleBuilder(t, fn, gcpolicy=gcpolicy) builder.generate_source(defines={'COUNT_OP_MALLOCS': 1}) builder.compile() builder.import_module() @@ -143,33 +143,36 @@ assert fn(0) == 5 def test_del_basic(): - S = lltype.GcStruct('S', ('x', lltype.Signed)) - lltype.attachRuntimeTypeInfo(S) - GLOBAL = lltype.Struct('GLOBAL', ('x', lltype.Signed)) - glob = lltype.malloc(GLOBAL, immortal=True) - def destructor(s): - glob.x = s.x + 1 - def type_info_S(s): - return lltype.getRuntimeTypeInfo(S) + for gcpolicy in [gc.RefcountingGcPolicy]: #, gc.FrameworkGcPolicy]: + S = lltype.GcStruct('S', ('x', lltype.Signed)) + TRASH = lltype.GcStruct('TRASH', ('x', lltype.Signed)) + lltype.attachRuntimeTypeInfo(S) + GLOBAL = lltype.Struct('GLOBAL', ('x', lltype.Signed)) + glob = lltype.malloc(GLOBAL, immortal=True) + def destructor(s): + glob.x = s.x + 1 + def type_info_S(s): + return lltype.getRuntimeTypeInfo(S) + + def g(n): + s = lltype.malloc(S) + s.x = n + # now 's' should go away + def entrypoint(n): + g(n) + # llop.gc__collect(lltype.Void) + return glob.x - def g(n): - s = lltype.malloc(S) - s.x = n - # now 's' should go away - def entrypoint(n): - g(n) - return glob.x - - t = TranslationContext() - t.buildannotator().build_types(entrypoint, [int]) - rtyper = t.buildrtyper() - destrptr = rtyper.annotate_helper_fn(destructor, [lltype.Ptr(S)]) - rtyper.attachRuntimeTypeInfoFunc(S, type_info_S, destrptr=destrptr) - rtyper.specialize() - fn = compile_func(entrypoint, None, t) + t = TranslationContext() + t.buildannotator().build_types(entrypoint, [int]) + rtyper = t.buildrtyper() + destrptr = rtyper.annotate_helper_fn(destructor, [lltype.Ptr(S)]) + rtyper.attachRuntimeTypeInfoFunc(S, type_info_S, destrptr=destrptr) + rtyper.specialize() + fn = compile_func(entrypoint, None, t, gcpolicy=gcpolicy) - res = fn(123) - assert res == 124 + res = fn(123) + assert res == 124 def test_del_catches(): import os From arigo at codespeak.net Sun May 7 12:12:41 2006 From: arigo at codespeak.net (arigo at codespeak.net) Date: Sun, 7 May 2006 12:12:41 +0200 (CEST) Subject: [pypy-svn] r26925 - in pypy/dist/pypy: rpython/memory translator/c translator/c/test Message-ID: <20060507101241.D6F1510079@code0.codespeak.net> Author: arigo Date: Sun May 7 12:12:39 2006 New Revision: 26925 Modified: pypy/dist/pypy/rpython/memory/gctransform.py pypy/dist/pypy/translator/c/database.py pypy/dist/pypy/translator/c/funcgen.py pypy/dist/pypy/translator/c/test/test_newgc.py Log: Support and some tests for GenC for these new OpaqueType usages. Modified: pypy/dist/pypy/rpython/memory/gctransform.py ============================================================================== --- pypy/dist/pypy/rpython/memory/gctransform.py (original) +++ pypy/dist/pypy/rpython/memory/gctransform.py Sun May 7 12:12:39 2006 @@ -602,6 +602,11 @@ return result elif isinstance(TYPE, lltype.Ptr) and TYPE._needsgc(): return [TYPE] + elif isinstance(TYPE, lltype.GcOpaqueType): + # heuristic: in theory the same problem exists with OpaqueType, but + # we use OpaqueType for other things too that we know are safely + # empty of further gc pointers + raise Exception("don't know what is in %r" % (TYPE,)) else: return [] Modified: pypy/dist/pypy/translator/c/database.py ============================================================================== --- pypy/dist/pypy/translator/c/database.py (original) +++ pypy/dist/pypy/translator/c/database.py Sun May 7 12:12:39 2006 @@ -5,6 +5,7 @@ from pypy.rpython.lltypesystem import lltype from pypy.rpython.lltypesystem.llmemory import Address from pypy.rpython.memory.lladdress import NULL +from pypy.tool.sourcetools import valid_identifier from pypy.translator.c.primitive import PrimitiveName, PrimitiveType from pypy.translator.c.primitive import PrimitiveErrorValue from pypy.translator.c.node import StructDefNode, ArrayDefNode @@ -129,7 +130,9 @@ who_asks.dependencies[node] = True return 'struct %s @' % node.name else: - raise Exception("don't know about opaque type %r" % (T,)) + #raise Exception("don't know about opaque type %r" % (T,)) + return 'struct %s @' % ( + valid_identifier('pypy_opaque_' + T.tag),) else: raise Exception("don't know about type %r" % (T,)) Modified: pypy/dist/pypy/translator/c/funcgen.py ============================================================================== --- pypy/dist/pypy/translator/c/funcgen.py (original) +++ pypy/dist/pypy/translator/c/funcgen.py Sun May 7 12:12:39 2006 @@ -592,6 +592,7 @@ OP_CAST_PTR_TO_ADR = OP_CAST_POINTER OP_CAST_ADR_TO_PTR = OP_CAST_POINTER + OP_CAST_OPAQUE_PTR = OP_CAST_POINTER def OP_CAST_INT_TO_PTR(self, op): TYPE = self.lltypemap(op.result) Modified: pypy/dist/pypy/translator/c/test/test_newgc.py ============================================================================== --- pypy/dist/pypy/translator/c/test/test_newgc.py (original) +++ pypy/dist/pypy/translator/c/test/test_newgc.py Sun May 7 12:12:39 2006 @@ -324,8 +324,8 @@ a.b = g(1) # this should trigger a couple of collections # XXX make sure it triggers at least one somehow! - for i in range(100000): - [A()] * 1000 + for i in range(1000): + [A() for j in range(1000)] return a.b fn = self.getcompiled(f) res = fn() @@ -355,8 +355,8 @@ b0.c = b.c = 42 # this should trigger a couple of collections # XXX make sure it triggers at least one somehow! - for i in range(100000): - [A()] * 1000 + for i in range(1000): + [A() for j in range(1000)] return global_a.b.a.b.c fn = self.getcompiled(f) startblock = self.t.graphs[0].startblock @@ -459,7 +459,7 @@ def f(): t.p = lltype.malloc(S) t.p.x = 43 - for i in range(1000000): + for i in range(2500000): s = lltype.malloc(S) s.x = i return t.p.x @@ -496,3 +496,30 @@ res = fn() assert res == 43 + 1000000 + def test_framework_opaque(self): + A = lltype.GcStruct('A', ('value', lltype.Signed)) + B = lltype.GcStruct('B', ('a', lltype.Ptr(A))) + O = lltype.GcOpaqueType('test.framework') + b = lltype.malloc(B) + b.a = lltype.malloc(A) + + def gethidden(n): + a = lltype.malloc(A) + a.value = -n * 7 + # we need to prevent it getting inlined + if n > 0: + gethidden(n-1) + return lltype.cast_opaque_ptr(lltype.Ptr(O), a) + def reveal(o): + return lltype.cast_opaque_ptr(lltype.Ptr(A), o) + def f(): + o = gethidden(10) + # this should trigger a collection + for i in range(2500000): + b.a.value = i + b.a = lltype.malloc(A) + a = reveal(o) + return a.value + fn = self.getcompiled(f) + res = fn() + assert res == -70 From cfbolz at codespeak.net Sun May 7 12:40:22 2006 From: cfbolz at codespeak.net (cfbolz at codespeak.net) Date: Sun, 7 May 2006 12:40:22 +0200 (CEST) Subject: [pypy-svn] r26926 - in pypy/dist/pypy: rpython/memory translator/c/test Message-ID: <20060507104022.BFC5610079@code0.codespeak.net> Author: cfbolz Date: Sun May 7 12:40:20 2006 New Revision: 26926 Modified: pypy/dist/pypy/rpython/memory/gctransform.py pypy/dist/pypy/translator/c/test/test_newgc.py Log: make the llop gc__collect work for the framework too Modified: pypy/dist/pypy/rpython/memory/gctransform.py ============================================================================== --- pypy/dist/pypy/rpython/memory/gctransform.py (original) +++ pypy/dist/pypy/rpython/memory/gctransform.py Sun May 7 12:40:20 2006 @@ -720,7 +720,7 @@ class CollectAnalyzer(graphanalyze.GraphAnalyzer): def operation_is_true(self, op): - return op.opname in ("malloc", "malloc_varsize") + return op.opname in ("malloc", "malloc_varsize", "gc__collect") class FrameworkGCTransformer(GCTransformer): @@ -875,6 +875,8 @@ GCData.GCClass.malloc_varsize.im_func, [s_gcdata] + [annmodel.SomeInteger(nonneg=True) for i in range(5)], annmodel.SomeAddress()) + collect_graph = annhelper.getgraph(GCData.GCClass.collect.im_func, + [s_gcdata], annmodel.s_None) annhelper.finish() # at this point, annotate all mix-level helpers self.frameworkgc_setup_ptr = self.graph2funcptr(frameworkgc_setup_graph) self.push_root_ptr = self.graph2funcptr(push_root_graph) @@ -883,8 +885,8 @@ self.graphs_to_inline[pop_root_graph] = True self.malloc_fixedsize_ptr = self.graph2funcptr(malloc_fixedsize_graph) self.malloc_varsize_ptr = self.graph2funcptr(malloc_varsize_graph) + self.collect_ptr = self.graph2funcptr(collect_graph) self.graphs_to_inline[malloc_fixedsize_graph] = True - self.collect_analyzer = CollectAnalyzer(self.translator) self.collect_analyzer.analyze_all() @@ -1061,6 +1063,14 @@ replace_malloc_varsize = replace_malloc + def replace_gc__collect(self, op, livevars, block): + # surely there's a better way of doing this? + s_gc = self.translator.annotator.bookkeeper.valueoftype(self.gcdata.GCClass) + r_gc = self.translator.rtyper.getrepr(s_gc) + const_gc = rmodel.inputconst(r_gc, self.gcdata.gc) + return [SpaceOperation( + "direct_call", [self.collect_ptr, const_gc], op.result)] + def push_alive_nopyobj(self, var): return [] Modified: pypy/dist/pypy/translator/c/test/test_newgc.py ============================================================================== --- pypy/dist/pypy/translator/c/test/test_newgc.py (original) +++ pypy/dist/pypy/translator/c/test/test_newgc.py Sun May 7 12:40:20 2006 @@ -7,6 +7,7 @@ from pypy.translator.backendopt.stat import print_statistics from pypy.translator.c import genc, gc from pypy.rpython.lltypesystem import lltype +from pypy.rpython.lltypesystem.lloperation import llop from pypy.rpython.objectmodel import cast_address_to_object, cast_object_to_address from pypy.rpython.memory.gctransform import GCTransformer @@ -323,9 +324,9 @@ a = A() a.b = g(1) # this should trigger a couple of collections - # XXX make sure it triggers at least one somehow! for i in range(1000): [A() for j in range(1000)] + llop.gc__collect(lltype.Void) return a.b fn = self.getcompiled(f) res = fn() @@ -353,10 +354,9 @@ g(1) b0 = a.b b0.c = b.c = 42 - # this should trigger a couple of collections - # XXX make sure it triggers at least one somehow! for i in range(1000): [A() for j in range(1000)] + llop.gc__collect(lltype.Void) return global_a.b.a.b.c fn = self.getcompiled(f) startblock = self.t.graphs[0].startblock @@ -378,6 +378,9 @@ # this should trigger 3 collections for i in range(1000000): prepare(B(), -1) + llop.gc__collect(lltype.Void) + llop.gc__collect(lltype.Void) + llop.gc__collect(lltype.Void) # we need to prevent it getting inlined if not a: g(A()) @@ -445,8 +448,7 @@ a.x = None def f(): a.x = A(42) - for i in range(1000000): - A(i) + llop.gc__collect(lltype.Void) return a.x.y fn = self.getcompiled(f) res = fn() From arigo at codespeak.net Sun May 7 12:40:33 2006 From: arigo at codespeak.net (arigo at codespeak.net) Date: Sun, 7 May 2006 12:40:33 +0200 (CEST) Subject: [pypy-svn] r26927 - in pypy/dist/pypy/rpython: lltypesystem lltypesystem/test test Message-ID: <20060507104033.8DBFB10083@code0.codespeak.net> Author: arigo Date: Sun May 7 12:40:32 2006 New Revision: 26927 Modified: pypy/dist/pypy/rpython/lltypesystem/lltype.py pypy/dist/pypy/rpython/lltypesystem/test/test_lltype.py pypy/dist/pypy/rpython/test/test_rptr.py Log: (arigo, pedronis) support for casts from opaque to opaque, likely needed for the stackless transform. Modified: pypy/dist/pypy/rpython/lltypesystem/lltype.py ============================================================================== --- pypy/dist/pypy/rpython/lltypesystem/lltype.py (original) +++ pypy/dist/pypy/rpython/lltypesystem/lltype.py Sun May 7 12:40:32 2006 @@ -646,9 +646,18 @@ and isinstance(PTRTYPE.TO, OpaqueType)): return opaqueptr(PTRTYPE.TO, 'hidden', container = ptr._obj, solid = ptr._solid) + elif (isinstance(CURTYPE.TO, OpaqueType) + and isinstance(PTRTYPE.TO, OpaqueType)): + try: + container = ptr._obj.container + except AttributeError: + raise RuntimeError("%r does not come from a container" % (ptr,)) + return opaqueptr(PTRTYPE.TO, 'hidden', + container = container, + solid = ptr._obj.solid) else: - raise TypeError("cast_opaque_ptr(): only between Opaque and " - "non-Opaque") + raise TypeError("invalid cast_opaque_ptr(): %r -> %r" % + (CURTYPE, PTRTYPE)) def direct_fieldptr(structptr, fieldname): """Get a pointer to a field in the struct. The resulting Modified: pypy/dist/pypy/rpython/lltypesystem/test/test_lltype.py ============================================================================== --- pypy/dist/pypy/rpython/lltypesystem/test/test_lltype.py (original) +++ pypy/dist/pypy/rpython/lltypesystem/test/test_lltype.py Sun May 7 12:40:32 2006 @@ -432,11 +432,14 @@ def test_cast_opaque_ptr(): O = GcOpaqueType('O') + Q = GcOpaqueType('Q') S = GcStruct('S', ('x', Signed)) s = malloc(S) o = cast_opaque_ptr(Ptr(O), s) assert typeOf(o).TO == O - p = cast_opaque_ptr(Ptr(S), o) + q = cast_opaque_ptr(Ptr(Q), o) + assert typeOf(q).TO == Q + p = cast_opaque_ptr(Ptr(S), q) assert typeOf(p).TO == S assert p == s O1 = OpaqueType('O') 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 Sun May 7 12:40:32 2006 @@ -121,11 +121,13 @@ def test_cast_opaque_ptr(): O = GcOpaqueType('O') + Q = GcOpaqueType('Q') S = GcStruct('S', ('x', Signed)) def fn(): s = malloc(S) o = cast_opaque_ptr(Ptr(O), s) - p = cast_opaque_ptr(Ptr(S), o) + q = cast_opaque_ptr(Ptr(Q), o) + p = cast_opaque_ptr(Ptr(S), q) return p == s res = interpret(fn, []) assert res is True From arigo at codespeak.net Sun May 7 13:33:26 2006 From: arigo at codespeak.net (arigo at codespeak.net) Date: Sun, 7 May 2006 13:33:26 +0200 (CEST) Subject: [pypy-svn] r26928 - in pypy/dist/pypy: annotation tool Message-ID: <20060507113326.C264D10077@code0.codespeak.net> Author: arigo Date: Sun May 7 13:33:25 2006 New Revision: 26928 Modified: pypy/dist/pypy/annotation/annrpython.py pypy/dist/pypy/tool/ansi_print.py Log: (pedronis, arigo) A strange hack to attach extra information to arbitrary exceptions. Modified: pypy/dist/pypy/annotation/annrpython.py ============================================================================== --- pypy/dist/pypy/annotation/annrpython.py (original) +++ pypy/dist/pypy/annotation/annrpython.py Sun May 7 13:33:25 2006 @@ -1,7 +1,7 @@ from __future__ import generators from types import ClassType, FunctionType -from pypy.tool.ansi_print import ansi_log +from pypy.tool.ansi_print import ansi_log, raise_nicer_exception from pypy.annotation import model as annmodel from pypy.annotation.pairtype import pair from pypy.annotation.bookkeeper import Bookkeeper @@ -656,7 +656,10 @@ for arg in argcells: if isinstance(arg, annmodel.SomeImpossibleValue): raise BlockedInference(self, op) - resultcell = consider_meth(*argcells) + try: + resultcell = consider_meth(*argcells) + except Exception: + raise_nicer_exception(op) if resultcell is None: resultcell = annmodel.SomeImpossibleValue() # no return value elif resultcell == annmodel.SomeImpossibleValue(): Modified: pypy/dist/pypy/tool/ansi_print.py ============================================================================== --- pypy/dist/pypy/tool/ansi_print.py (original) +++ pypy/dist/pypy/tool/ansi_print.py Sun May 7 13:33:25 2006 @@ -64,3 +64,20 @@ file=self.file, newline=newline, flush=flush) ansi_log = AnsiLog() + +# ____________________________________________________________ +# Nice helper + +def raise_nicer_exception(*extraargs): + cls, e, tb = sys.exc_info() + str_e = str(e) + class ExcSubclass(cls): + def __str__(self): + lines = [str_e] + for extra in extraargs: + lines.append('\t.. %r' % (extra,)) + return '\n'.join(lines) + ExcSubclass.__name__ = cls.__name__ + "'" + ExcSubclass.__module__ = cls.__module__ + e.__class__ = ExcSubclass + raise ExcSubclass, e, tb From arigo at codespeak.net Sun May 7 13:35:59 2006 From: arigo at codespeak.net (arigo at codespeak.net) Date: Sun, 7 May 2006 13:35:59 +0200 (CEST) Subject: [pypy-svn] r26929 - in pypy/dist/pypy: rpython/memory translator/backendopt translator/c/test Message-ID: <20060507113559.6581610077@code0.codespeak.net> Author: arigo Date: Sun May 7 13:35:53 2006 New Revision: 26929 Modified: pypy/dist/pypy/rpython/memory/gctransform.py pypy/dist/pypy/rpython/memory/support.py pypy/dist/pypy/translator/backendopt/inline.py pypy/dist/pypy/translator/c/test/test_newgc.py Log: (pedronis, arigo) * review test_newgc for the real intention being the gc__collect() places. * fix two minor but segfaulting bugs in the gc. * functions with an attribute 'dont_inline=True' are never inlined. Modified: pypy/dist/pypy/rpython/memory/gctransform.py ============================================================================== --- pypy/dist/pypy/rpython/memory/gctransform.py (original) +++ pypy/dist/pypy/rpython/memory/gctransform.py Sun May 7 13:35:53 2006 @@ -1068,8 +1068,11 @@ s_gc = self.translator.annotator.bookkeeper.valueoftype(self.gcdata.GCClass) r_gc = self.translator.rtyper.getrepr(s_gc) const_gc = rmodel.inputconst(r_gc, self.gcdata.gc) - return [SpaceOperation( - "direct_call", [self.collect_ptr, const_gc], op.result)] + newop = SpaceOperation( + "direct_call", [self.collect_ptr, const_gc], op.result) + ops, index = self.protect_roots(newop, livevars, block, + block.operations.index(op)) + return ops def push_alive_nopyobj(self, var): return [] Modified: pypy/dist/pypy/rpython/memory/support.py ============================================================================== --- pypy/dist/pypy/rpython/memory/support.py (original) +++ pypy/dist/pypy/rpython/memory/support.py Sun May 7 13:35:53 2006 @@ -31,12 +31,12 @@ _alloc_flavor_ = "raw" def __init__(self): - self.chunk = NULL + self.chunk = unused_chunks.get() def append(self, addr): if addr == NULL: return - if self.chunk == NULL or self.chunk.signed[1] == chunk_size: + if self.chunk.signed[1] == chunk_size: new = unused_chunks.get() new.address[0] = self.chunk new.signed[1] = 0 Modified: pypy/dist/pypy/translator/backendopt/inline.py ============================================================================== --- pypy/dist/pypy/translator/backendopt/inline.py (original) +++ pypy/dist/pypy/translator/backendopt/inline.py Sun May 7 13:35:53 2006 @@ -496,7 +496,7 @@ static_instruction_count(graph)) -def static_callers(translator, ignore_primitives=False): +def inlinable_static_callers(translator): result = [] def build_call_graph(node): if isinstance(node, Block): @@ -505,10 +505,12 @@ funcobj = op.args[0].value._obj graph = getattr(funcobj, 'graph', None) if graph is not None: - if ignore_primitives: - if getattr(getattr(funcobj, '_callable', None), - 'suggested_primitive', False): - continue + if getattr(getattr(funcobj, '_callable', None), + 'suggested_primitive', False): + continue + if getattr(getattr(funcobj, '_callable', None), + 'dont_inline', False): + continue result.append((parentgraph, graph)) for parentgraph in translator.graphs: traverse(build_call_graph, parentgraph) @@ -522,7 +524,7 @@ callers = {} # {graph: {graphs-that-call-it}} callees = {} # {graph: {graphs-that-it-calls}} if callgraph is None: - callgraph = static_callers(translator, ignore_primitives=True) + callgraph = inlinable_static_callers(translator) for graph1, graph2 in callgraph: callers.setdefault(graph2, {})[graph1] = True callees.setdefault(graph1, {})[graph2] = True Modified: pypy/dist/pypy/translator/c/test/test_newgc.py ============================================================================== --- pypy/dist/pypy/translator/c/test/test_newgc.py (original) +++ pypy/dist/pypy/translator/c/test/test_newgc.py Sun May 7 13:35:53 2006 @@ -315,17 +315,24 @@ class TestUsingFramework(AbstractTestClass): from pypy.translator.c.gc import FrameworkGcPolicy as gcpolicy + def test_empty_collect(self): + def f(): + llop.gc__collect(lltype.Void) + fn = self.getcompiled(f) + fn() + def test_framework_simple(self): def g(x): # cannot cause a collect return x + 1 class A(object): pass - def f(): + def make(): a = A() a.b = g(1) - # this should trigger a couple of collections - for i in range(1000): - [A() for j in range(1000)] + return a + make.dont_inline = True + def f(): + a = make() llop.gc__collect(lltype.Void) return a.b fn = self.getcompiled(f) @@ -339,14 +346,15 @@ pass class B(object): pass - def g(x): # can cause a collect - return B() + def g(x): # cause a collect + llop.gc__collect(lltype.Void) + g.dont_inline = True global_a = A() global_a.b = B() global_a.b.a = A() global_a.b.a.b = B() global_a.b.a.b.c = 1 - def f(): + def make(): global_a.b.a.b.c = 40 a = global_a.b.a b = a.b @@ -354,8 +362,9 @@ g(1) b0 = a.b b0.c = b.c = 42 - for i in range(1000): - [A() for j in range(1000)] + make.dont_inline = True + def f(): + make() llop.gc__collect(lltype.Void) return global_a.b.a.b.c fn = self.getcompiled(f) @@ -375,16 +384,11 @@ b.a = a b.othervalue = 5 def g(a): - # this should trigger 3 collections - for i in range(1000000): - prepare(B(), -1) - llop.gc__collect(lltype.Void) llop.gc__collect(lltype.Void) - llop.gc__collect(lltype.Void) - # we need to prevent it getting inlined - if not a: - g(A()) + for i in range(1000): + prepare(B(), -1) # probably overwrites collected memory return a.value + g.dont_inline = True def f(): b = B() prepare(b, 123) @@ -446,8 +450,11 @@ self.y = y a = A(0) a.x = None - def f(): + def make(): a.x = A(42) + make.dont_inline = True + def f(): + make() llop.gc__collect(lltype.Void) return a.x.y fn = self.getcompiled(f) @@ -500,26 +507,23 @@ def test_framework_opaque(self): A = lltype.GcStruct('A', ('value', lltype.Signed)) - B = lltype.GcStruct('B', ('a', lltype.Ptr(A))) O = lltype.GcOpaqueType('test.framework') - b = lltype.malloc(B) - b.a = lltype.malloc(A) def gethidden(n): a = lltype.malloc(A) a.value = -n * 7 - # we need to prevent it getting inlined - if n > 0: - gethidden(n-1) return lltype.cast_opaque_ptr(lltype.Ptr(O), a) + gethidden.dont_inline = True def reveal(o): return lltype.cast_opaque_ptr(lltype.Ptr(A), o) + def overwrite(a, i): + a.value = i + overwrite.dont_inline = True def f(): o = gethidden(10) - # this should trigger a collection - for i in range(2500000): - b.a.value = i - b.a = lltype.malloc(A) + llop.gc__collect(lltype.Void) + for i in range(1000): # overwrite freed memory + overwrite(lltype.malloc(A), i) a = reveal(o) return a.value fn = self.getcompiled(f) From ericvrp at codespeak.net Sun May 7 14:38:50 2006 From: ericvrp at codespeak.net (ericvrp at codespeak.net) Date: Sun, 7 May 2006 14:38:50 +0200 (CEST) Subject: [pypy-svn] r26933 - pypy/dist/pypy/doc Message-ID: <20060507123850.74B5E10078@code0.codespeak.net> Author: ericvrp Date: Sun May 7 14:38:48 2006 New Revision: 26933 Modified: pypy/dist/pypy/doc/getting-started.txt Log: You need llvm 1.7 (not 1.6) currently. (thank you Elmo for spotting this) Modified: pypy/dist/pypy/doc/getting-started.txt ============================================================================== --- pypy/dist/pypy/doc/getting-started.txt (original) +++ pypy/dist/pypy/doc/getting-started.txt Sun May 7 14:38:48 2006 @@ -384,7 +384,7 @@ +++++++++++++++++++++++++++++++++++++++ To translate for LLVM (`low level virtual machine`_) you must first have `LLVM -installed with version 1.6`_ - the `how to install LLVM`_ provides some helpful +installed with version 1.7`_ - the `how to install LLVM`_ provides some helpful hints. Please note that you do not need the CFrontend to compile, make tools-only. From arigo at codespeak.net Sun May 7 20:16:07 2006 From: arigo at codespeak.net (arigo at codespeak.net) Date: Sun, 7 May 2006 20:16:07 +0200 (CEST) Subject: [pypy-svn] r26946 - pypy/dist/pypy/rpython/memory Message-ID: <20060507181607.9D29610075@code0.codespeak.net> Author: arigo Date: Sun May 7 20:16:06 2006 New Revision: 26946 Modified: pypy/dist/pypy/rpython/memory/support.py Log: Bug fix for the previous check-in. Modified: pypy/dist/pypy/rpython/memory/support.py ============================================================================== --- pypy/dist/pypy/rpython/memory/support.py (original) +++ pypy/dist/pypy/rpython/memory/support.py Sun May 7 20:16:06 2006 @@ -32,6 +32,8 @@ def __init__(self): self.chunk = unused_chunks.get() + self.chunk.address[0] = NULL + self.chunk.signed[1] = 0 def append(self, addr): if addr == NULL: @@ -60,7 +62,7 @@ self.chunk.signed[1] = used_chunks - 1 return result - def free(self): + def free(self): # XXX very inefficient while self.pop() != NULL: pass return AddressLinkedList From arigo at codespeak.net Sun May 7 21:20:21 2006 From: arigo at codespeak.net (arigo at codespeak.net) Date: Sun, 7 May 2006 21:20:21 +0200 (CEST) Subject: [pypy-svn] r26951 - in pypy/dist/pypy/rpython/lltypesystem: . test Message-ID: <20060507192021.6C43910076@code0.codespeak.net> Author: arigo Date: Sun May 7 21:20:20 2006 New Revision: 26951 Modified: pypy/dist/pypy/rpython/lltypesystem/llmemory.py pypy/dist/pypy/rpython/lltypesystem/test/test_llmemory.py Log: (pedronis, arigo) Support for casting back from address to a pointer with a different "opaqueness". Modified: pypy/dist/pypy/rpython/lltypesystem/llmemory.py ============================================================================== --- pypy/dist/pypy/rpython/lltypesystem/llmemory.py (original) +++ pypy/dist/pypy/rpython/lltypesystem/llmemory.py Sun May 7 21:20:20 2006 @@ -228,6 +228,9 @@ # special case that requires direct_fieldptr return lltype.direct_fieldptr(ref.struct, ref.fieldname) + elif (isinstance(EXPECTED_TYPE.TO, lltype.OpaqueType) or + isinstance(ref.type().TO, lltype.OpaqueType)): + return lltype.cast_opaque_ptr(EXPECTED_TYPE, ref.get()) else: # regular case return lltype.cast_pointer(EXPECTED_TYPE, ref.get()) Modified: pypy/dist/pypy/rpython/lltypesystem/test/test_llmemory.py ============================================================================== --- pypy/dist/pypy/rpython/lltypesystem/test/test_llmemory.py (original) +++ pypy/dist/pypy/rpython/lltypesystem/test/test_llmemory.py Sun May 7 21:20:20 2006 @@ -182,3 +182,14 @@ subarray = cast_adr_to_ptr(adr, lltype.Ptr(SUBARRAY)) subarray[0] = 121 assert s.y == 121 + +def test_opaque(): + S = lltype.GcStruct('S', ('x', lltype.Signed), ('y', lltype.Signed)) + O = lltype.GcOpaqueType('O') + s = lltype.malloc(S) + adr = cast_ptr_to_adr(s) + o = cast_adr_to_ptr(adr, lltype.Ptr(O)) + assert lltype.cast_opaque_ptr(lltype.Ptr(S), o) == s + adr2 = cast_ptr_to_adr(o) + s2 = cast_adr_to_ptr(adr2, lltype.Ptr(S)) + assert s2 == s From arigo at codespeak.net Sun May 7 21:23:50 2006 From: arigo at codespeak.net (arigo at codespeak.net) Date: Sun, 7 May 2006 21:23:50 +0200 (CEST) Subject: [pypy-svn] r26953 - in pypy/dist/pypy: rpython translator/c/test translator/stackless translator/stackless/test Message-ID: <20060507192350.B537F10076@code0.codespeak.net> Author: arigo Date: Sun May 7 21:23:48 2006 New Revision: 26953 Modified: pypy/dist/pypy/rpython/extfunctable.py pypy/dist/pypy/translator/c/test/test_stackless.py pypy/dist/pypy/translator/stackless/code.py pypy/dist/pypy/translator/stackless/test/test_yield_current_frame_to_caller.py pypy/dist/pypy/translator/stackless/transform.py Log: (pedronis, arigo) Finished the basic yield_current_frame_to_caller() and switch() on top of the stackless transformer. Modified: pypy/dist/pypy/rpython/extfunctable.py ============================================================================== --- pypy/dist/pypy/rpython/extfunctable.py (original) +++ pypy/dist/pypy/rpython/extfunctable.py Sun May 7 21:23:48 2006 @@ -28,12 +28,14 @@ class ExtTypeInfo: - def __init__(self, typ, tag, methods, needs_container=True): + def __init__(self, typ, tag, methods, + needs_container=True, needs_gc=False): self.typ = typ self.tag = tag self._TYPE = None self.methods = methods # {'name': ExtFuncInfo()} self.needs_container = needs_container + self.needs_gc = needs_gc def get_annotation(self, methodname): return self.methods[methodname].annotation @@ -50,7 +52,10 @@ def get_lltype(self): if self._TYPE is None: from pypy.rpython.lltypesystem import lltype - OPAQUE = lltype.OpaqueType(self.tag) + if self.needs_gc: + OPAQUE = lltype.GcOpaqueType(self.tag) + else: + OPAQUE = lltype.OpaqueType(self.tag) OPAQUE._exttypeinfo = self if self.needs_container: STRUCT = lltype.GcStruct(self.tag, ('obj', OPAQUE)) @@ -93,7 +98,7 @@ return info typetable = {} -def declaretype1(typ, tag, methodsdecl, needs_container): +def declaretype1(typ, tag, methodsdecl, needs_container, needs_gc=False): assert isinstance(typ, type) methods = {} for name, args in methodsdecl.items(): @@ -105,7 +110,7 @@ else: func = None # failed (typical for old-style C types), ignore it methods[name] = declare(func, *args) - info = ExtTypeInfo(typ, tag, methods, needs_container) + info = ExtTypeInfo(typ, tag, methods, needs_container, needs_gc) typetable[typ] = info for callback in table_callbacks: callback() @@ -117,6 +122,10 @@ def declareptrtype(typ, tag, **methodsdecl): return declaretype1(typ, tag, methodsdecl, needs_container=False) +def declaregcptrtype(typ, tag, **methodsdecl): + return declaretype1(typ, tag, methodsdecl, needs_container=False, + needs_gc=True) + # _____________________________________________________________ def record_call(func, args_s, symbol): @@ -242,7 +251,7 @@ declare(rstack.stack_too_big, bool, 'll_stack/too_big') declare(rstack.stack_check, noneannotation, 'll_stack/check') declare(rstack.stack_unwind, noneannotation, 'll_stack/unwind') -frametop_type_info = declareptrtype(rstack.frame_stack_top, 'frame_stack_top', +frametop_type_info = declaregcptrtype(rstack.frame_stack_top,'frame_stack_top', switch = (rstack.frame_stack_top, 'll_stackless/switch')) Modified: pypy/dist/pypy/translator/c/test/test_stackless.py ============================================================================== --- pypy/dist/pypy/translator/c/test/test_stackless.py (original) +++ pypy/dist/pypy/translator/c/test/test_stackless.py Sun May 7 21:23:48 2006 @@ -13,7 +13,14 @@ class TestStackless(object): gcpolicy = None # Refcounting - + + def setup_class(cls): + # to re-enable this, remove the two characters 'gc' in the + # declaregcptrtype(rstack.frame_stack_top,...) call in + # rpython/extfunctable. Doing so breaks translator/stackless/. + import py + py.test.skip("stackless + refcounting doesn't work any more for now") + def wrap_stackless_function(self, fn): def entry_point(argv): os.write(1, str(fn())+"\n") Modified: pypy/dist/pypy/translator/stackless/code.py ============================================================================== --- pypy/dist/pypy/translator/stackless/code.py (original) +++ pypy/dist/pypy/translator/stackless/code.py Sun May 7 21:23:48 2006 @@ -1,5 +1,6 @@ from pypy.rpython.lltypesystem import lltype, llmemory, lloperation from pypy.rpython import rarithmetic +from pypy.rpython import extfunctable def ll_frame_switch(state): @@ -29,7 +30,7 @@ global_state.top = null_state global_state.restart_substate = 0 origin_state = llmemory.cast_adr_to_ptr(fetch_retval_void_p(), - lltype.Ptr(STATE_HEADER)) + OPAQUE_STATE_HEADER_PTR) return origin_state ll_frame_switch.stackless_explicit = True @@ -43,6 +44,9 @@ null_state = lltype.nullptr(STATE_HEADER) +OPAQUE_STATE_HEADER_PTR = lltype.Ptr( + extfunctable.frametop_type_info.get_lltype()) + ##def decode_state(currentframe): ## return (currentframe.function, ## currentframe.retval_type, @@ -88,7 +92,7 @@ global_state.top = null_state global_state.restart_substate = 0 origin_state = llmemory.cast_adr_to_ptr(fetch_retval_void_p(), - lltype.Ptr(STATE_HEADER)) + OPAQUE_STATE_HEADER_PTR) return origin_state else: global_state.restart_substate = 0 Modified: pypy/dist/pypy/translator/stackless/test/test_yield_current_frame_to_caller.py ============================================================================== --- pypy/dist/pypy/translator/stackless/test/test_yield_current_frame_to_caller.py (original) +++ pypy/dist/pypy/translator/stackless/test/test_yield_current_frame_to_caller.py Sun May 7 21:23:48 2006 @@ -1,58 +1,75 @@ from pypy.translator.stackless.test.test_transform import \ llinterp_stackless_function, run_stackless_function from pypy.translator.stackless import code +from pypy.rpython import rstack import py import os -#py.test.skip('in progress') -def test_simple(): - def f(ignored): - c = g() - return 1 - def g(): - code.yield_current_frame_to_caller() - - data = llinterp_stackless_function(f) - assert data == 1 - - -def test_switch(): - def f(ignored): - c = g() - c.switch() - return 1 - def g(): - d = code.yield_current_frame_to_caller() - return d - - data = llinterp_stackless_function(f) - assert data == 1 - - -def test_yield_frame(): - - def g(lst): - lst.append(2) - frametop_before_5 = code.yield_current_frame_to_caller() - lst.append(4) - frametop_before_7 = frametop_before_5.switch() - lst.append(6) - return frametop_before_7 - - def f(ignored): - lst = [1] - frametop_before_4 = g(lst) - lst.append(3) - frametop_before_6 = frametop_before_4.switch() - lst.append(5) - frametop_after_return = frametop_before_6.switch() - lst.append(7) - assert bool(frametop_after_return) - n = 0 - for i in lst: - n = n*10 + i - return n - - data = llinterp_stackless_function(f) - assert data == 1234567 +class TestFromCode: + yield_current_frame_to_caller = staticmethod( + code.yield_current_frame_to_caller) + switch = staticmethod(code.ll_frame_switch) + + def _freeze_(self): + return True + + def test_simple(self): + def f(ignored): + c = g() + return 1 + def g(): + self.yield_current_frame_to_caller() + + data = llinterp_stackless_function(f) + assert data == 1 + + + def test_switch(self): + def f(ignored): + c = g() + self.switch(c) + return 1 + def g(): + d = self.yield_current_frame_to_caller() + return d + + data = llinterp_stackless_function(f) + assert data == 1 + + + def test_yield_frame(self): + + def g(lst): + lst.append(2) + frametop_before_5 = self.yield_current_frame_to_caller() + lst.append(4) + frametop_before_7 = self.switch(frametop_before_5) + lst.append(6) + return frametop_before_7 + + def f(ignored): + lst = [1] + frametop_before_4 = g(lst) + lst.append(3) + frametop_before_6 = self.switch(frametop_before_4) + lst.append(5) + frametop_after_return = self.switch(frametop_before_6) + lst.append(7) + assert bool(frametop_after_return) + n = 0 + for i in lst: + n = n*10 + i + return n + + data = llinterp_stackless_function(f) + assert data == 1234567 + + +class TestFromRStack(TestFromCode): + yield_current_frame_to_caller = staticmethod( + rstack.yield_current_frame_to_caller) + + def switch(state): + return state.switch() + switch = staticmethod(switch) Modified: pypy/dist/pypy/translator/stackless/transform.py ============================================================================== --- pypy/dist/pypy/translator/stackless/transform.py (original) +++ pypy/dist/pypy/translator/stackless/transform.py Sun May 7 21:23:48 2006 @@ -118,13 +118,13 @@ self.fetch_retval_void_p_ptr = mixlevelannotator.constfunc( code.fetch_retval_void_p, [], annmodel.SomeAddress()) - s_StatePtr = annmodel.SomePtr(lltype.Ptr(code.STATE_HEADER)) + s_StatePtr = annmodel.SomePtr(code.OPAQUE_STATE_HEADER_PTR) self.stack_frames_depth_ptr = mixlevelannotator.constfunc( code.stack_frames_depth, [], annmodel.SomeInteger()) -## self.yield_current_frame_to_caller_ptr = mixlevelannotator.constfunc( -## code.yield_current_frame_to_caller, [], s_StatePtr) -## self.ll_frame_switch_ptr = mixlevelannotator.constfunc( -## code.ll_frame_switch, [s_StatePtr], s_StatePtr) + self.yield_current_frame_to_caller_ptr = mixlevelannotator.constfunc( + code.yield_current_frame_to_caller, [], s_StatePtr) + self.ll_frame_switch_ptr = mixlevelannotator.constfunc( + code.ll_frame_switch, [s_StatePtr], s_StatePtr) mixlevelannotator.finish() @@ -328,18 +328,26 @@ edata = self.translator.rtyper.getexceptiondata() etype = edata.lltype_of_exception_type evalue = edata.lltype_of_exception_value - + + def replace_with_call(fnptr): + args = [fnptr] + op.args[1:] + newop = model.SpaceOperation('direct_call', args, op.result) + block.operations[i] = newop + return newop + while i < len(block.operations): op = block.operations[i] + if op.opname == 'yield_current_frame_to_caller': + op = replace_with_call(self.yield_current_frame_to_caller_ptr) + if op.opname in ('direct_call', 'indirect_call'): # trap calls to stackless-related suggested primitives if op.opname == 'direct_call': func = getattr(op.args[0].value._obj, '_callable', None) if func is ll_stackless.ll_stackless_stack_frames_depth: - op = model.SpaceOperation( - 'direct_call', [self.stack_frames_depth_ptr], - op.result) - block.operations[i] = op + op = replace_with_call(self.stack_frames_depth_ptr) + elif func is ll_stackless.ll_stackless_switch: + op = replace_with_call(self.ll_frame_switch_ptr) if i == len(block.operations) - 1 \ and block.exitswitch == model.c_last_exception: From arigo at codespeak.net Sun May 7 21:39:35 2006 From: arigo at codespeak.net (arigo at codespeak.net) Date: Sun, 7 May 2006 21:39:35 +0200 (CEST) Subject: [pypy-svn] r26954 - in pypy/dist/pypy: rpython/lltypesystem translator/stackless translator/stackless/test Message-ID: <20060507193935.AF71310076@code0.codespeak.net> Author: arigo Date: Sun May 7 21:39:33 2006 New Revision: 26954 Modified: pypy/dist/pypy/rpython/lltypesystem/lloperation.py pypy/dist/pypy/translator/stackless/code.py pypy/dist/pypy/translator/stackless/test/test_transform.py pypy/dist/pypy/translator/stackless/test/test_yield_current_frame_to_caller.py Log: (pedronis, arigo) Compile yield_current_etc() and switch() with GenC. Added a missing 'canraise' in lloperation for yield_current_etc(), which actually raises UnwindException. Modified: pypy/dist/pypy/rpython/lltypesystem/lloperation.py ============================================================================== --- pypy/dist/pypy/rpython/lltypesystem/lloperation.py (original) +++ pypy/dist/pypy/rpython/lltypesystem/lloperation.py Sun May 7 21:39:33 2006 @@ -67,6 +67,11 @@ hop.exception_is_here() return hop.genop(op.opname, args_v, resulttype=hop.r_result.lowleveltype) + +class StackException(Exception): + """Base for internal exceptions possibly used by the stackless + implementation.""" + # ____________________________________________________________ # # This list corresponds to the operations implemented by the LLInterpreter. @@ -311,7 +316,7 @@ # __________ stackless operation(s) __________ - 'yield_current_frame_to_caller': LLOp(), + 'yield_current_frame_to_caller': LLOp(canraise=(StackException,)), # __________ misc operations __________ Modified: pypy/dist/pypy/translator/stackless/code.py ============================================================================== --- pypy/dist/pypy/translator/stackless/code.py (original) +++ pypy/dist/pypy/translator/stackless/code.py Sun May 7 21:39:33 2006 @@ -158,7 +158,7 @@ llmemory.Address, fn) call_function.stackless_explicit = True -class UnwindException(Exception): +class UnwindException(lloperation.StackException): def __init__(self): # during unwind, global_state.top points to frame that first caught # the UnwindException, whilst frame_bottom points to the frame Modified: pypy/dist/pypy/translator/stackless/test/test_transform.py ============================================================================== --- pypy/dist/pypy/translator/stackless/test/test_transform.py (original) +++ pypy/dist/pypy/translator/stackless/test/test_transform.py Sun May 7 21:39:33 2006 @@ -190,7 +190,7 @@ t.stacklesstransformer = StacklessTransformer(t) - cbuilder = CStandaloneBuilder(t, entry_point) + cbuilder = CStandaloneBuilder(t, entry_point, gcpolicy=gc.BoehmGcPolicy) cbuilder.generate_source() if conftest.option.view: t.view() Modified: pypy/dist/pypy/translator/stackless/test/test_yield_current_frame_to_caller.py ============================================================================== --- pypy/dist/pypy/translator/stackless/test/test_yield_current_frame_to_caller.py (original) +++ pypy/dist/pypy/translator/stackless/test/test_yield_current_frame_to_caller.py Sun May 7 21:39:33 2006 @@ -24,6 +24,8 @@ data = llinterp_stackless_function(f) assert data == 1 + res = run_stackless_function(f) + assert res.strip() == "1" def test_switch(self): def f(ignored): @@ -37,6 +39,8 @@ data = llinterp_stackless_function(f) assert data == 1 + res = run_stackless_function(f) + assert res.strip() == "1" def test_yield_frame(self): @@ -65,6 +69,9 @@ data = llinterp_stackless_function(f) assert data == 1234567 + res = run_stackless_function(f) + assert res.strip() == "1234567" + class TestFromRStack(TestFromCode): yield_current_frame_to_caller = staticmethod( From arigo at codespeak.net Sun May 7 23:59:06 2006 From: arigo at codespeak.net (arigo at codespeak.net) Date: Sun, 7 May 2006 23:59:06 +0200 (CEST) Subject: [pypy-svn] r26958 - in pypy/dist/pypy: annotation rpython rpython/lltypesystem rpython/lltypesystem/test translator/c/src translator/c/test translator/stackless translator/stackless/test Message-ID: <20060507215906.C337210083@code0.codespeak.net> Author: arigo Date: Sun May 7 23:59:02 2006 New Revision: 26958 Modified: pypy/dist/pypy/annotation/builtin.py pypy/dist/pypy/annotation/unaryop.py pypy/dist/pypy/rpython/lltypesystem/llmemory.py pypy/dist/pypy/rpython/lltypesystem/lltype.py pypy/dist/pypy/rpython/lltypesystem/test/test_lltype.py pypy/dist/pypy/rpython/rbuiltin.py pypy/dist/pypy/rpython/rexternalobj.py pypy/dist/pypy/rpython/rmodel.py pypy/dist/pypy/translator/c/src/exception.h pypy/dist/pypy/translator/c/test/test_stackless.py pypy/dist/pypy/translator/c/test/test_tasklets.py pypy/dist/pypy/translator/stackless/code.py pypy/dist/pypy/translator/stackless/test/test_depth.py pypy/dist/pypy/translator/stackless/test/test_transform.py pypy/dist/pypy/translator/stackless/test/test_yield_current_frame_to_caller.py pypy/dist/pypy/translator/stackless/transform.py Log: (pedronis, arigo) Good progress on the stackless transformer front. The big change is that the old stackless no longer work with reference counting! They still pass with boehm. The big result is that the old test pass with the new stackless transform. Lots of pushing and pulling: * details of cast_opaque_ptr() * bool(external object) * bool(address) * bug fix in yield_curr_etc() * added stack_unwind() * always put an explicit Exception link after direct_call * etc. Modified: pypy/dist/pypy/annotation/builtin.py ============================================================================== --- pypy/dist/pypy/annotation/builtin.py (original) +++ pypy/dist/pypy/annotation/builtin.py Sun May 7 23:59:02 2006 @@ -426,11 +426,8 @@ def cast_opaque_ptr(PtrT, s_p): assert isinstance(s_p, SomePtr), "casting of non-pointer: %r" % s_p assert PtrT.is_constant() - try: - lltype.cast_opaque_ptr(PtrT.const, s_p.ll_ptrtype._defl()) - except RuntimeError: - pass # the type checks passed, but the _defl opaque cannot be cast - return SomePtr(ll_ptrtype=PtrT.const) + cast_p = lltype.cast_opaque_ptr(PtrT.const, s_p.ll_ptrtype._defl()) + return SomePtr(ll_ptrtype=lltype.typeOf(cast_p)) def direct_fieldptr(s_p, s_fieldname): assert isinstance(s_p, SomePtr), "direct_* of non-pointer: %r" % s_p Modified: pypy/dist/pypy/annotation/unaryop.py ============================================================================== --- pypy/dist/pypy/annotation/unaryop.py (original) +++ pypy/dist/pypy/annotation/unaryop.py Sun May 7 23:59:02 2006 @@ -667,3 +667,6 @@ return SomeTypedAddressAccess( lladdress.supported_access_types[s_attr.const]) getattr.can_only_throw = [] + + def is_true(s_addr): + return SomeBool() Modified: pypy/dist/pypy/rpython/lltypesystem/llmemory.py ============================================================================== --- pypy/dist/pypy/rpython/lltypesystem/llmemory.py (original) +++ pypy/dist/pypy/rpython/lltypesystem/llmemory.py Sun May 7 23:59:02 2006 @@ -187,6 +187,9 @@ return fakeaddress(self.ob, offset) return NotImplemented + def __nonzero__(self): + return self.ob is not None + def __eq__(self, other): if not isinstance(other, fakeaddress): return False @@ -215,6 +218,8 @@ self.ref().set(value) def _cast_to_ptr(self, EXPECTED_TYPE): + if not self: + return lltype.nullptr(EXPECTED_TYPE.TO) ref = self.ref() if (isinstance(ref, _arrayitemref) and isinstance(EXPECTED_TYPE.TO, lltype.FixedSizeArray) and Modified: pypy/dist/pypy/rpython/lltypesystem/lltype.py ============================================================================== --- pypy/dist/pypy/rpython/lltypesystem/lltype.py (original) +++ pypy/dist/pypy/rpython/lltypesystem/lltype.py Sun May 7 23:59:02 2006 @@ -632,6 +632,8 @@ "%s to %s" % (CURTYPE, PTRTYPE)) if (isinstance(CURTYPE.TO, OpaqueType) and not isinstance(PTRTYPE.TO, OpaqueType)): + if not ptr: + return nullptr(PTRTYPE.TO) try: container = ptr._obj.container except AttributeError: @@ -644,10 +646,14 @@ return _ptr(PTRTYPE, container, solid) elif (not isinstance(CURTYPE.TO, OpaqueType) and isinstance(PTRTYPE.TO, OpaqueType)): + if not ptr: + return nullptr(PTRTYPE.TO) return opaqueptr(PTRTYPE.TO, 'hidden', container = ptr._obj, solid = ptr._solid) elif (isinstance(CURTYPE.TO, OpaqueType) and isinstance(PTRTYPE.TO, OpaqueType)): + if not ptr: + return nullptr(PTRTYPE.TO) try: container = ptr._obj.container except AttributeError: Modified: pypy/dist/pypy/rpython/lltypesystem/test/test_lltype.py ============================================================================== --- pypy/dist/pypy/rpython/lltypesystem/test/test_lltype.py (original) +++ pypy/dist/pypy/rpython/lltypesystem/test/test_lltype.py Sun May 7 23:59:02 2006 @@ -299,7 +299,19 @@ p10 = cast_pointer(Ptr(S1), p0) assert typeOf(p10) == Ptr(S1) assert not p10 - + +def test_nullptr_opaque_cast(): + S = Struct('S') + p0 = nullptr(S) + O1 = OpaqueType('O1') + O2 = OpaqueType('O2') + p1 = cast_opaque_ptr(Ptr(O1), p0) + assert not p1 + p2 = cast_opaque_ptr(Ptr(O2), p1) + assert not p2 + p3 = cast_opaque_ptr(Ptr(S), p2) + assert not p3 + def test_hash(): S = ForwardReference() Modified: pypy/dist/pypy/rpython/rbuiltin.py ============================================================================== --- pypy/dist/pypy/rpython/rbuiltin.py (original) +++ pypy/dist/pypy/rpython/rbuiltin.py Sun May 7 23:59:02 2006 @@ -378,7 +378,7 @@ } _cast_from_Signed = { lltype.Signed: None, - lltype.Bool: 'cast_int_to_bool', + lltype.Bool: 'int_is_true', lltype.Char: 'cast_int_to_char', lltype.UniChar: 'cast_int_to_unichar', lltype.Float: 'cast_int_to_float', Modified: pypy/dist/pypy/rpython/rexternalobj.py ============================================================================== --- pypy/dist/pypy/rpython/rexternalobj.py (original) +++ pypy/dist/pypy/rpython/rexternalobj.py Sun May 7 23:59:02 2006 @@ -44,3 +44,7 @@ init_opaque_object(p.obj, value) self.instance_cache[key] = p return p + + def rtype_is_true(self, hop): + vlist = hop.inputargs(self) + return hop.genop('ptr_nonzero', vlist, resulttype=lltype.Bool) Modified: pypy/dist/pypy/rpython/rmodel.py ============================================================================== --- pypy/dist/pypy/rpython/rmodel.py (original) +++ pypy/dist/pypy/rpython/rmodel.py Sun May 7 23:59:02 2006 @@ -202,7 +202,9 @@ try: vlen = self.rtype_len(hop) except MissingRTypeOperation: - return hop.inputconst(Bool, True) + if not hop.s_result.is_constant(): + raise TyperError("rtype_is_true(%r) not implemented" % (self,)) + return hop.inputconst(Bool, hop.s_result.const) else: return hop.genop('int_is_true', [vlen], resulttype=Bool) Modified: pypy/dist/pypy/translator/c/src/exception.h ============================================================================== --- pypy/dist/pypy/translator/c/src/exception.h (original) +++ pypy/dist/pypy/translator/c/src/exception.h Sun May 7 23:59:02 2006 @@ -10,6 +10,9 @@ #ifdef HAVE_RTYPER /* RPython version of exceptions */ /******************************************************************/ +/* Hint: functions and macros not defined here, like RPyRaiseException, + come from exctransformer via the table in extfunc.py. */ + #define RPyFetchException(etypevar, evaluevar, type_of_evaluevar) do { \ etypevar = RPyFetchExceptionType(); \ evaluevar = (type_of_evaluevar)RPyFetchExceptionValue(); \ Modified: pypy/dist/pypy/translator/c/test/test_stackless.py ============================================================================== --- pypy/dist/pypy/translator/c/test/test_stackless.py (original) +++ pypy/dist/pypy/translator/c/test/test_stackless.py Sun May 7 23:59:02 2006 @@ -40,7 +40,8 @@ #cbuilder.use_stackless_transformation = True cbuilder.generate_source() cbuilder.compile() - return cbuilder.cmdexec('') + res = cbuilder.cmdexec('') + return int(res.strip()) def test_stack_depth(self): @@ -62,8 +63,8 @@ count10 = f(10) return count10 - count0 - data = self.wrap_stackless_function(fn) - assert data.strip() == '10' + res = self.wrap_stackless_function(fn) + assert res == 10 def test_stack_withptr(self): def f(n): @@ -78,8 +79,8 @@ count10, _ = f(10) return count10 - count0 - data = self.wrap_stackless_function(fn) - assert data.strip() == '10' + res = self.wrap_stackless_function(fn) + assert res == 10 def test_stackless_manytimes(self): def f(n): @@ -95,8 +96,8 @@ count10, _ = f(100) return count10 - count0 - data = self.wrap_stackless_function(fn) - assert data.strip() == '100' + res = self.wrap_stackless_function(fn) + assert res == 100 def test_stackless_arguments(self): def f(n, d, t): @@ -109,10 +110,14 @@ def fn(): count0, d, t = f(0, 5.5, (1, 2)) count10, d, t = f(10, 5.5, (1, 2)) - return "[" + str(count10 - count0) + ", " + str(d) + ", " + str(t[0]) + ", " + str(t[1]) + "]" + result = (count10 - count0) * 1000000 + result += t[0] * 10000 + result += t[1] * 100 + result += int(d*10) + return result - data = self.wrap_stackless_function(fn) - assert eval(data) == [10, 5.5, 1, 2] + res = self.wrap_stackless_function(fn) + assert res == 10010255 def test_stack_too_big(self): @@ -135,8 +140,8 @@ def fn(): return f(0) - data = self.wrap_stackless_function(fn) - assert int(data.strip()) > 500 + res = self.wrap_stackless_function(fn) + assert res > 500 def test_stack_unwind(self): @@ -144,8 +149,8 @@ stack_unwind() return 42 - data = self.wrap_stackless_function(f) - assert int(data.strip()) == 42 + res = self.wrap_stackless_function(f) + assert res == 42 def test_auto_stack_unwind(self): def f(n): @@ -155,8 +160,8 @@ def fn(): return f(10**6) - data = self.wrap_stackless_function(fn) - assert int(data.strip()) == 704 + res = self.wrap_stackless_function(fn) + assert res == 704 def test_yield_frame(self): @@ -182,8 +187,8 @@ n = n*10 + i return n - data = self.wrap_stackless_function(f) - assert int(data.strip()) == 1234567 + res = self.wrap_stackless_function(f) + assert res == 1234567 def test_foo(self): def f(): @@ -193,8 +198,8 @@ def g(): d = yield_current_frame_to_caller() return d - data = self.wrap_stackless_function(f) - assert data.strip() == '1' + res = self.wrap_stackless_function(f) + assert res == 1 def test_yield_noswitch_frame(self): @@ -219,8 +224,8 @@ n = n*10 + i return n - data = self.wrap_stackless_function(f) - assert int(data.strip()) == 12345 + res = self.wrap_stackless_function(f) + assert res == 12345 # tested with refcounting too for sanity checking def test_yield_frame_mem_pressure(self): @@ -261,8 +266,8 @@ n = n*10 + i return n - data = self.wrap_stackless_function(f) - assert int(data.strip()) == 1234567 + res = self.wrap_stackless_function(f) + assert res == 1234567 # ____________________________________________________________ @@ -291,3 +296,12 @@ if not check_boehm_presence(): py.test.skip("Boehm GC not present") +# ____________________________________________________________ + +class TestStacklessTransformBoehm(TestStacklessBoehm): + + def wrap_stackless_function(self, fn): + # temporary way of doing this + #import py; py.test.skip("in-progress") + from pypy.translator.stackless.test import test_transform + return test_transform.run_stackless_function(fn) Modified: pypy/dist/pypy/translator/c/test/test_tasklets.py ============================================================================== --- pypy/dist/pypy/translator/c/test/test_tasklets.py (original) +++ pypy/dist/pypy/translator/c/test/test_tasklets.py Sun May 7 23:59:02 2006 @@ -13,6 +13,11 @@ gcpolicy = None if cbuild.check_boehm_presence(): gcpolicy = BoehmGcPolicy +else: + # to re-enable this, remove the two characters 'gc' in the + # declaregcptrtype(rstack.frame_stack_top,...) call in + # rpython/extfunctable. Doing so breaks translator/stackless/. + py.test.skip("stackless + refcounting doesn't work any more for now") # count of loops in tests (set lower to speed up) loops = 1 Modified: pypy/dist/pypy/translator/stackless/code.py ============================================================================== --- pypy/dist/pypy/translator/stackless/code.py (original) +++ pypy/dist/pypy/translator/stackless/code.py Sun May 7 23:59:02 2006 @@ -99,6 +99,7 @@ next_state = llmemory.cast_adr_to_ptr(fetch_retval_void_p(), lltype.Ptr(STATE_HEADER)) global_state.top = next_state + global_state.retval_void_p = llmemory.NULL raise UnwindException() yield_current_frame_to_caller.stackless_explicit = True @@ -126,6 +127,23 @@ return depth stack_frames_depth.stackless_explicit = True +def ll_stack_unwind(): + if not global_state.restart_substate: + u = UnwindException() + s = lltype.malloc(STATE_HEADER) + s.restartstate = 1 + # the next three lines are pure rtyper-pleasing hacks + f = ll_stack_unwind + if global_state.restart_substate: + f = None + s.function = llmemory.cast_ptr_to_adr(f) + s.retval_type = RETVAL_VOID + add_frame_state(u, s) + raise u + else: + global_state.restart_substate = 0 +ll_stack_unwind.stackless_explicit = True + class StacklessData: def __init__(self): self.top = null_state Modified: pypy/dist/pypy/translator/stackless/test/test_depth.py ============================================================================== --- pypy/dist/pypy/translator/stackless/test/test_depth.py (original) +++ pypy/dist/pypy/translator/stackless/test/test_depth.py Sun May 7 23:59:02 2006 @@ -27,7 +27,7 @@ g2(g1) return res - def fn(ignored): + def fn(): count0 = f(0) count10 = f(10) return count10 - count0 @@ -36,7 +36,7 @@ assert res == 10 res = run_stackless_function(fn) - assert res.strip() == "10" + assert res == 10 def test_with_ptr(self): def f(n): @@ -46,7 +46,7 @@ res = self.stack_frames_depth(), 1 return res - def fn(ignored): + def fn(): count0, _ = f(0) count10, _ = f(10) return count10 - count0 @@ -55,7 +55,7 @@ assert res == 10 res = run_stackless_function(fn) - assert res.strip() == "10" + assert res == 10 def test_manytimes(self): def f(n): @@ -65,7 +65,7 @@ res = self.stack_frames_depth(), 1 return res - def fn(ignored): + def fn(): count0, _ = f(0) count10, _ = f(100) return count10 - count0 @@ -74,7 +74,7 @@ assert res == 100 res = run_stackless_function(fn) - assert res.strip() == "100" + assert res == 100 def test_arguments(self): def f(n, d, t): @@ -84,7 +84,7 @@ res = self.stack_frames_depth(), d, t return res - def fn(ignored): + def fn(): count0, d, t = f(0, 5.5, (1, 2)) count10, d, t = f(10, 5.5, (1, 2)) return count10 - count0 + int(d) @@ -93,7 +93,7 @@ assert res == 15 res = run_stackless_function(fn) - assert res.strip() == "15" + assert res == 15 class TestFromRStack(TestFromCode): Modified: pypy/dist/pypy/translator/stackless/test/test_transform.py ============================================================================== --- pypy/dist/pypy/translator/stackless/test/test_transform.py (original) +++ pypy/dist/pypy/translator/stackless/test/test_transform.py Sun May 7 23:59:02 2006 @@ -34,8 +34,18 @@ from pypy.translator.stackless import code +def factorial(n): + if n > 1: + return factorial(n-1) * n + else: + return 1 + +def one(): # but the annotator doesn't know it's one + return factorial(5) / 120 + + def test_nothing(): - def fn(ignored): + def fn(): return 21 res = llinterp_stackless_function(fn) assert res == 21 @@ -48,8 +58,8 @@ def g(x): check(x) return x + 1 - def example(x): - return g(x) + 1 + def example(): + return g(one()) + 1 res = llinterp_stackless_function(example) assert res == 3 @@ -60,8 +70,8 @@ def g(x): check(x) return x + 0.125 - def example(x): - return int((g(x) + 1)*1000.0) + def example(): + return int((g(one()) + 1)*1000.0) res = llinterp_stackless_function(example) assert res == 2125 @@ -72,10 +82,10 @@ def g(x): check(x) return x + 1 - def example(x): - return g(x) + 1 + def example(): + return g(one()) + 1 res = run_stackless_function(example) - assert res.strip() == "3" + assert res == 3 def test_protected_call(): def check(x): @@ -84,16 +94,16 @@ def g(x): check(x) return x + 1 - def example(x): + def example(): try: - y = g(x) + y = g(one()) except Exception: y = -1 return y + 1 res = llinterp_stackless_function(example) assert res == 3 res = run_stackless_function(example) - assert res == "3" + assert res == 3 def test_resume_with_exception(): def check(x): @@ -107,8 +117,8 @@ return x + 1 def h(x): return g(x) - def example(x): - y = h(x) + def example(): + y = h(one()) return y + 1 info = py.test.raises( llinterp.LLException, @@ -127,9 +137,9 @@ return x + 1 def h(x): return g(x) - def example(x): + def example(): try: - y = h(x) + y = h(one()) except KeyError: y = -1 return y + 1 @@ -141,7 +151,8 @@ if x: raise code.UnwindException check.stackless_explicit = True - def f(l): + def f(): + l = one() check(l) return len([x for x in range(l)]) res = llinterp_stackless_function(f) @@ -171,6 +182,9 @@ raise Exception, "this probably isn't going to work" t.buildrtyper().specialize() + from pypy.translator.transform import insert_ll_stackcheck + insert_ll_stackcheck(t) + if conftest.option.view: t.view() return t @@ -178,7 +192,7 @@ def run_stackless_function(fn): def entry_point(argv): try: - r = fn(len(argv)) + r = fn() except code.UnwindException, u: code.slp_main_loop() r = code.global_state.retval_long @@ -195,12 +209,13 @@ if conftest.option.view: t.view() cbuilder.compile() - return cbuilder.cmdexec('').strip() + res = cbuilder.cmdexec('') + return int(res.strip()) def llinterp_stackless_function(fn): def entry_point(argv): try: - r = fn(len(argv)) + r = fn() except code.UnwindException, u: code.slp_main_loop() return code.global_state.retval_long Modified: pypy/dist/pypy/translator/stackless/test/test_yield_current_frame_to_caller.py ============================================================================== --- pypy/dist/pypy/translator/stackless/test/test_yield_current_frame_to_caller.py (original) +++ pypy/dist/pypy/translator/stackless/test/test_yield_current_frame_to_caller.py Sun May 7 23:59:02 2006 @@ -15,7 +15,7 @@ return True def test_simple(self): - def f(ignored): + def f(): c = g() return 1 def g(): @@ -25,10 +25,10 @@ assert data == 1 res = run_stackless_function(f) - assert res.strip() == "1" + assert res == 1 def test_switch(self): - def f(ignored): + def f(): c = g() self.switch(c) return 1 @@ -40,7 +40,7 @@ assert data == 1 res = run_stackless_function(f) - assert res.strip() == "1" + assert res == 1 def test_yield_frame(self): @@ -52,7 +52,7 @@ lst.append(6) return frametop_before_7 - def f(ignored): + def f(): lst = [1] frametop_before_4 = g(lst) lst.append(3) @@ -60,7 +60,7 @@ lst.append(5) frametop_after_return = self.switch(frametop_before_6) lst.append(7) - assert bool(frametop_after_return) + assert not frametop_after_return n = 0 for i in lst: n = n*10 + i @@ -70,7 +70,7 @@ assert data == 1234567 res = run_stackless_function(f) - assert res.strip() == "1234567" + assert res == 1234567 class TestFromRStack(TestFromCode): Modified: pypy/dist/pypy/translator/stackless/transform.py ============================================================================== --- pypy/dist/pypy/translator/stackless/transform.py (original) +++ pypy/dist/pypy/translator/stackless/transform.py Sun May 7 23:59:02 2006 @@ -10,7 +10,7 @@ from pypy.rpython.rclass import getinstancerepr from pypy.rpython.rbuiltin import gen_cast from pypy.rpython.rtyper import LowLevelOpList -from pypy.rpython.module import ll_stackless +from pypy.rpython.module import ll_stackless, ll_stack from pypy.translator.stackless.code import STATE_HEADER, null_state @@ -119,12 +119,19 @@ code.fetch_retval_void_p, [], annmodel.SomeAddress()) s_StatePtr = annmodel.SomePtr(code.OPAQUE_STATE_HEADER_PTR) - self.stack_frames_depth_ptr = mixlevelannotator.constfunc( - code.stack_frames_depth, [], annmodel.SomeInteger()) + self.suggested_primitives = { + ll_stackless.ll_stackless_stack_frames_depth: + mixlevelannotator.constfunc( + code.stack_frames_depth, [], annmodel.SomeInteger()), + ll_stackless.ll_stackless_switch: + mixlevelannotator.constfunc( + code.ll_frame_switch, [s_StatePtr], s_StatePtr), + ll_stack.ll_stack_unwind: + mixlevelannotator.constfunc( + code.ll_stack_unwind, [], annmodel.s_None), + } self.yield_current_frame_to_caller_ptr = mixlevelannotator.constfunc( code.yield_current_frame_to_caller, [], s_StatePtr) - self.ll_frame_switch_ptr = mixlevelannotator.constfunc( - code.ll_frame_switch, [s_StatePtr], s_StatePtr) mixlevelannotator.finish() @@ -344,10 +351,8 @@ # trap calls to stackless-related suggested primitives if op.opname == 'direct_call': func = getattr(op.args[0].value._obj, '_callable', None) - if func is ll_stackless.ll_stackless_stack_frames_depth: - op = replace_with_call(self.stack_frames_depth_ptr) - elif func is ll_stackless.ll_stackless_switch: - op = replace_with_call(self.ll_frame_switch_ptr) + if func in self.suggested_primitives: + op = replace_with_call(self.suggested_primitives[func]) if i == len(block.operations) - 1 \ and block.exitswitch == model.c_last_exception: @@ -357,23 +362,22 @@ return else: link = support.split_block_with_keepalive(block, i+1) - # this section deserves a whinge: - - # i want to use rtyper.insert_link_conversions() in - # insert_resume_handling(). insert_link_conversions() - # calls bindingrepr(), which depends on variables having - # annotations. split_block called copyvar(None, ...) - # which doesn't preserve the annotation. so put it back - # here. it certainly sucks that this module has to worry - # about annotations :( -## XXX is this still needed? -## ann = self.translator.annotator -## for f, t in zip(link.args, link.target.inputargs): -## nb = ann.binding(f, None) -## if nb is not None: -## ann.setbinding(t, nb) block.exitswitch = model.c_last_exception link.llexitcase = None + # add a general Exception link, because all calls can + # raise anything + v_exctype = varoftype(etype) + v_excvalue = varoftype(evalue) + newlink = model.Link([v_exctype, v_excvalue], + self.curr_graph.exceptblock, + Exception) + newlink.last_exception = v_exctype + newlink.last_exc_value = v_excvalue + newexits = list(block.exits) + newexits.append(newlink) + block.recloseblock(*newexits) + self.translator.rtyper._convert_link(block, newlink) + var_unwind_exception = varoftype(evalue) # for the case where we are resuming to an except: From pedronis at codespeak.net Mon May 8 11:34:41 2006 From: pedronis at codespeak.net (pedronis at codespeak.net) Date: Mon, 8 May 2006 11:34:41 +0200 (CEST) Subject: [pypy-svn] r26961 - pypy/dist/pypy/translator/c/test Message-ID: <20060508093441.0FE7910070@code0.codespeak.net> Author: pedronis Date: Mon May 8 11:34:39 2006 New Revision: 26961 Modified: pypy/dist/pypy/translator/c/test/test_stackless.py pypy/dist/pypy/translator/c/test/test_tasklets.py Log: run the tasklets tests with the transform too. avoid some code repetition in the tests. Modified: pypy/dist/pypy/translator/c/test/test_stackless.py ============================================================================== --- pypy/dist/pypy/translator/c/test/test_stackless.py (original) +++ pypy/dist/pypy/translator/c/test/test_stackless.py Mon May 8 11:34:39 2006 @@ -1,4 +1,5 @@ from pypy.translator.translator import TranslationContext +from pypy.translator.backendopt.all import backend_optimizations from pypy.translator.c.genc import CStandaloneBuilder from pypy.translator.c import gc from pypy.annotation.model import SomeList, SomeString @@ -8,18 +9,22 @@ import os -# ____________________________________________________________ - - -class TestStackless(object): - gcpolicy = None # Refcounting +class StacklessTest(object): + backendopt = False def setup_class(cls): - # to re-enable this, remove the two characters 'gc' in the - # declaregcptrtype(rstack.frame_stack_top,...) call in - # rpython/extfunctable. Doing so breaks translator/stackless/. import py - py.test.skip("stackless + refcounting doesn't work any more for now") + if cls.gcpolicy is None: + # to re-enable this, remove the two characters 'gc' in the + # declaregcptrtype(rstack.frame_stack_top,...) call in + # rpython/extfunctable. Doing so breaks translator/stackless/. + import py + py.test.skip("stackless + refcounting doesn't work any more for now") + else: + assert cls.gcpolicy is gc.BoehmGcPolicy + from pypy.translator.tool.cbuild import check_boehm_presence + if not check_boehm_presence(): + py.test.skip("Boehm GC not present") def wrap_stackless_function(self, fn): def entry_point(argv): @@ -31,6 +36,8 @@ t = TranslationContext() t.buildannotator().build_types(entry_point, [s_list_of_strings]) t.buildrtyper().specialize() + if self.backendopt: + backend_optimizations(t) from pypy.translator.transform import insert_ll_stackcheck insert_ll_stackcheck(t) @@ -43,6 +50,11 @@ res = cbuilder.cmdexec('') return int(res.strip()) +# ____________________________________________________________ + + +class TestStackless(StacklessTest): + gcpolicy = None # Refcounting def test_stack_depth(self): def g1(): @@ -290,11 +302,6 @@ class TestStacklessBoehm(TestStackless): gcpolicy = gc.BoehmGcPolicy - def setup_class(cls): - import py - from pypy.translator.tool.cbuild import check_boehm_presence - if not check_boehm_presence(): - py.test.skip("Boehm GC not present") # ____________________________________________________________ Modified: pypy/dist/pypy/translator/c/test/test_tasklets.py ============================================================================== --- pypy/dist/pypy/translator/c/test/test_tasklets.py (original) +++ pypy/dist/pypy/translator/c/test/test_tasklets.py Mon May 8 11:34:39 2006 @@ -8,16 +8,8 @@ # For testing from pypy.translator.tool import cbuild -from pypy.translator.c.gc import BoehmGcPolicy - -gcpolicy = None -if cbuild.check_boehm_presence(): - gcpolicy = BoehmGcPolicy -else: - # to re-enable this, remove the two characters 'gc' in the - # declaregcptrtype(rstack.frame_stack_top,...) call in - # rpython/extfunctable. Doing so breaks translator/stackless/. - py.test.skip("stackless + refcounting doesn't work any more for now") +from pypy.translator.c import gc +from pypy.translator.c.test import test_stackless # count of loops in tests (set lower to speed up) loops = 1 @@ -32,34 +24,6 @@ globals = Globals() globals.count = 0 -def wrap_stackless_function(fn): - # ensure we have no SomeObject s - from pypy.annotation.policy import AnnotatorPolicy - annotatorpolicy = AnnotatorPolicy() - annotatorpolicy.allow_someobjects = False - - from pypy.translator.translator import TranslationContext - from pypy.translator.c.genc import CStandaloneBuilder - from pypy.annotation.model import SomeList, SomeString - from pypy.annotation.listdef import ListDef - from pypy.translator.backendopt.all import backend_optimizations - - def entry_point(argv): - os.write(1, str(fn())) - return 0 - - s_list_of_strings = SomeList(ListDef(None, SomeString())) - s_list_of_strings.listdef.resize() - t = TranslationContext() - t.buildannotator(annotatorpolicy).build_types(entry_point, [s_list_of_strings]) - t.buildrtyper().specialize() - backend_optimizations(t) - cbuilder = CStandaloneBuilder(t, entry_point, gcpolicy=gcpolicy) - cbuilder.stackless = True - cbuilder.generate_source() - cbuilder.compile() - return cbuilder.cmdexec('') - # ____________________________________________________________ class ThreadLocals(object): @@ -230,301 +194,315 @@ # ____________________________________________________________ -def test_simplex(): - - class Tasklet1(Tasklet): - def fn(self): - for ii in range(5): - globals.count += 1 - schedule() +class TestTasklets(test_stackless.StacklessTest): + gcpolicy = gc.BoehmGcPolicy + backendopt = True + + def test_simplex(self): + + class Tasklet1(Tasklet): + def fn(self): + for ii in range(5): + globals.count += 1 + schedule() - def f(): - for ii in range(loops): - Tasklet1().start() - run() - return globals.count == loops * 5 + def f(): + for ii in range(loops): + Tasklet1().start() + run() + return globals.count == loops * 5 + + res = self.wrap_stackless_function(f) + print res + assert res == 1 + + def test_multiple_simple(self): + + class Tasklet1(Tasklet): + def fn(self): + for ii in range(5): + globals.count += 1 + schedule() - res = wrap_stackless_function(f) - print res - assert res == '1' + class Tasklet2(Tasklet): + def fn(self): + for ii in range(5): + globals.count += 1 + schedule() + globals.count += 1 -def test_multiple_simple(): - - class Tasklet1(Tasklet): - def fn(self): - for ii in range(5): - globals.count += 1 + class Tasklet3(Tasklet): + def fn(self): schedule() - - class Tasklet2(Tasklet): - def fn(self): - for ii in range(5): - globals.count += 1 + for ii in range(10): + globals.count += 1 + if ii % 2: + schedule() schedule() - globals.count += 1 - class Tasklet3(Tasklet): - def fn(self): - schedule() - for ii in range(10): - globals.count += 1 - if ii % 2: + def f(): + for ii in range(loops): + Tasklet1().start() + Tasklet2().start() + Tasklet3().start() + run() + return globals.count == loops * 25 + + res = self.wrap_stackless_function(f) + assert res == 1 + + def test_schedule_remove(self): + + class Tasklet1(Tasklet): + def fn(self): + for ii in range(20): + if ii < 10: + schedule() + else: + schedule_remove() + globals.count += 1 + + def f(): + for ii in range(loops): + Tasklet1().start() + run() + for ii in range(loops): + Tasklet1().start() + run() + return globals.count == loops * 10 * 2 + + res = self.wrap_stackless_function(f) + assert res == 1 + + def test_run_immediately(self): + globals.intermediate = 0 + class Tasklet1(Tasklet): + def fn(self): + for ii in range(20): + globals.count += 1 schedule() - schedule() - - def f(): - for ii in range(loops): - Tasklet1().start() - Tasklet2().start() - Tasklet3().start() - run() - return globals.count == loops * 25 - - res = wrap_stackless_function(f) - assert res == '1' -def test_schedule_remove(): + class RunImmediate(Tasklet): + def fn(self): + globals.intermediate = globals.count + schedule() - class Tasklet1(Tasklet): - def fn(self): - for ii in range(20): - if ii < 10: + class Tasklet2(Tasklet): + def fn(self): + for ii in range(20): + globals.count += 1 + if ii == 10: + RunImmediate().run() schedule() - else: - schedule_remove() - globals.count += 1 - def f(): - for ii in range(loops): - Tasklet1().start() - run() - for ii in range(loops): - Tasklet1().start() - run() - return globals.count == loops * 10 * 2 + def f(): + Tasklet2().start() + for ii in range(loops): + Tasklet1().start() + run() + total_expected = (loops + 1) * 20 + return (globals.intermediate == total_expected / 2 + 1 and + globals.count == total_expected) - res = wrap_stackless_function(f) - assert res == '1' + res = self.wrap_stackless_function(f) + assert res == 1 -def test_run_immediately(): - globals.intermediate = 0 - class Tasklet1(Tasklet): - def fn(self): - for ii in range(20): - globals.count += 1 - schedule() + def test_channel1(self): + ch = Channel() - class RunImmediate(Tasklet): - def fn(self): - globals.intermediate = globals.count - schedule() - - class Tasklet2(Tasklet): - def fn(self): - for ii in range(20): - globals.count += 1 - if ii == 10: - RunImmediate().run() - schedule() + class Tasklet1(Tasklet): + def fn(self): + for ii in range(5): + ch.send(ii) + + class Tasklet2(Tasklet): + def fn(self): + #while True: XXX Doesnt annotate + for ii in range(6): + globals.count += ch.receive() - def f(): - Tasklet2().start() - for ii in range(loops): + def f(): + Tasklet2().start() Tasklet1().start() - run() - total_expected = (loops + 1) * 20 - return (globals.intermediate == total_expected / 2 + 1 and - globals.count == total_expected) + run() + return (globals.count == 10) - res = wrap_stackless_function(f) - assert res == '1' + res = self.wrap_stackless_function(f) + assert res == 1 -def test_channel1(): - ch = Channel() - - class Tasklet1(Tasklet): - def fn(self): - for ii in range(5): - ch.send(ii) - - class Tasklet2(Tasklet): - def fn(self): - #while True: XXX Doesnt annotate - for ii in range(6): - globals.count += ch.receive() - - def f(): - Tasklet2().start() - Tasklet1().start() - run() - return (globals.count == 10) + def test_channel2(self): - res = wrap_stackless_function(f) - assert res == '1' + class Tasklet1(Tasklet): + def __init__(self, ch): + self.ch = ch + def fn(self): + for ii in range(5): + self.ch.send(ii) + + class Tasklet2(Tasklet): + def __init__(self, ch): + self.ch = ch + def fn(self): + #while True:XXX Doesnt annotate + for ii in range(6): + res = self.ch.receive() + globals.count += res + + def f(): + ch = Channel() + Tasklet1(ch).start() + Tasklet2(ch).start() + run() + return globals.count == 10 + + res = self.wrap_stackless_function(f) + assert res == 1 + + def test_channel3(self): + + class Tasklet1(Tasklet): + def __init__(self, ch): + self.ch = ch + def fn(self): + for ii in range(5): + self.ch.send(ii) + + class Tasklet2(Tasklet): + def __init__(self, ch): + self.ch = ch + def fn(self): + #while True: XXX Doesnt annotate + for ii in range(16): + res = self.ch.receive() + globals.count += res + + def f(): + ch = Channel() + Tasklet1(ch).start() + Tasklet1(ch).start() + Tasklet1(ch).start() + Tasklet2(ch).start() + run() + return globals.count == 30 + + res = self.wrap_stackless_function(f) + assert res == 1 + + def test_flexible_channels(self): + """ test with something other than int """ + + class A(object): + def __init__(self, num): + self.num = num + def getvalue(self): + res = self.num + self.num *= 2 + return res + + class Data(object): + pass + + class IntData(Data): + def __init__(self, i): + self.int = i + + class StringData(Data): + def __init__(self, s): + self.str = s + + class InstanceData(Data): + def __init__(self, i): + self.instance = i + + + class Tasklet1(Tasklet): + def __init__(self, ch): + self.ch = ch + def fn(self): + for ii in range(5): + self.ch.send(IntData(ii)) + + class Tasklet2(Tasklet): + def __init__(self, ch, strdata): + self.ch = ch + self.strdata = strdata + def fn(self): + for ii in range(5): + self.ch.send(StringData(self.strdata)) + + class Tasklet3(Tasklet): + def __init__(self, ch, instance): + self.ch = ch + self.instance = instance + def fn(self): + for ii in range(5): + self.ch.send(InstanceData(self.instance)) + + class Server(Tasklet): + def __init__(self, ch): + self.ch = ch + self.loop = True + + def stop(self): + self.loop = False + + def fn(self): + while self.loop: + data = self.ch.receive() + if isinstance(data, IntData): + globals.count += data.int + elif isinstance(data, StringData): + globals.count += len(data.str) + elif isinstance(data, InstanceData): + globals.count += data.instance.getvalue() -def test_channel2(): - - class Tasklet1(Tasklet): - def __init__(self, ch): - self.ch = ch - def fn(self): - for ii in range(5): - self.ch.send(ii) - - class Tasklet2(Tasklet): - def __init__(self, ch): - self.ch = ch - def fn(self): - #while True:XXX Doesnt annotate - for ii in range(6): - res = self.ch.receive() - globals.count += res - - def f(): ch = Channel() - Tasklet1(ch).start() - Tasklet2(ch).start() - run() - return globals.count == 10 + server = Server(ch) - res = wrap_stackless_function(f) - assert res == '1' + def f(): + Tasklet1(ch).start() + Tasklet2(ch, "abcd").start() + Tasklet2(ch, "xxx").start() + Tasklet3(ch, A(1)).start() + server.start() + run() + return globals.count == (0+1+2+3+4) + (5*4) + (5*3) + (1+2+4+8+16) + + res = self.wrap_stackless_function(f) + assert res == 1 + + def test_original_api(self): + + class TaskletAsFunction(Tasklet): + def __init__(self, fn): + self.redirect_fn = fn + def fn(self): + self.redirect_fn() -def test_channel3(): - - class Tasklet1(Tasklet): - def __init__(self, ch): - self.ch = ch - def fn(self): - for ii in range(5): - self.ch.send(ii) - - class Tasklet2(Tasklet): - def __init__(self, ch): - self.ch = ch - def fn(self): - #while True: XXX Doesnt annotate - for ii in range(16): - res = self.ch.receive() - globals.count += res - - def f(): - ch = Channel() - Tasklet1(ch).start() - Tasklet1(ch).start() - Tasklet1(ch).start() - Tasklet2(ch).start() - run() - return globals.count == 30 - - res = wrap_stackless_function(f) - assert res == '1' - -def test_flexible_channels(): - """ test with something other than int """ - - class A(object): - def __init__(self, num): - self.num = num - def getvalue(self): - res = self.num - self.num *= 2 - return res - - class Data(object): - pass - - class IntData(Data): - def __init__(self, i): - self.int = i - - class StringData(Data): - def __init__(self, s): - self.str = s - - class InstanceData(Data): - def __init__(self, i): - self.instance = i - - - class Tasklet1(Tasklet): - def __init__(self, ch): - self.ch = ch - def fn(self): - for ii in range(5): - self.ch.send(IntData(ii)) + def tasklet(fn): + return TaskletAsFunction(fn) - class Tasklet2(Tasklet): - def __init__(self, ch, strdata): - self.ch = ch - self.strdata = strdata - def fn(self): + def simple(): for ii in range(5): - self.ch.send(StringData(self.strdata)) + globals.count += 1 + schedule() - class Tasklet3(Tasklet): - def __init__(self, ch, instance): - self.ch = ch - self.instance = instance - def fn(self): - for ii in range(5): - self.ch.send(InstanceData(self.instance)) - - class Server(Tasklet): - def __init__(self, ch): - self.ch = ch - self.loop = True - - def stop(self): - self.loop = False + def f(): + for ii in range(loops): + tasklet(simple).start() + run() + run() + return globals.count == loops * 5 - def fn(self): - while self.loop: - data = self.ch.receive() - if isinstance(data, IntData): - globals.count += data.int - elif isinstance(data, StringData): - globals.count += len(data.str) - elif isinstance(data, InstanceData): - globals.count += data.instance.getvalue() - - ch = Channel() - server = Server(ch) + res = self.wrap_stackless_function(f) + assert res == 1 - def f(): - Tasklet1(ch).start() - Tasklet2(ch, "abcd").start() - Tasklet2(ch, "xxx").start() - Tasklet3(ch, A(1)).start() - server.start() - run() - return globals.count == (0+1+2+3+4) + (5*4) + (5*3) + (1+2+4+8+16) - - res = wrap_stackless_function(f) - assert res == '1' - -def test_original_api(): - - class TaskletAsFunction(Tasklet): - def __init__(self, fn): - self.redirect_fn = fn - def fn(self): - self.redirect_fn() +# ____________________________________________________________ - def tasklet(fn): - return TaskletAsFunction(fn) - - def simple(): - for ii in range(5): - globals.count += 1 - schedule() - - def f(): - for ii in range(loops): - tasklet(simple).start() - run() - run() - return globals.count == loops * 5 +class TestTaskletsStacklessTransform(TestTasklets): - res = wrap_stackless_function(f) - assert res == '1' + def wrap_stackless_function(self, fn): + # temporary way of doing this + #import py; py.test.skip("in-progress") + from pypy.translator.stackless.test import test_transform + return test_transform.run_stackless_function(fn) From ericvrp at codespeak.net Mon May 8 14:36:11 2006 From: ericvrp at codespeak.net (ericvrp at codespeak.net) Date: Mon, 8 May 2006 14:36:11 +0200 (CEST) Subject: [pypy-svn] r26963 - in pypy/dist/pypy/translator: . goal Message-ID: <20060508123611.CA36C10070@code0.codespeak.net> Author: ericvrp Date: Mon May 8 14:36:10 2006 New Revision: 26963 Modified: pypy/dist/pypy/translator/driver.py pypy/dist/pypy/translator/goal/translate.py Log: Enable Javscript translations of standalone targets. Modified: pypy/dist/pypy/translator/driver.py ============================================================================== --- pypy/dist/pypy/translator/driver.py (original) +++ pypy/dist/pypy/translator/driver.py Mon May 8 14:36:10 2006 @@ -404,6 +404,26 @@ task_run_squeak = taskdef(task_run_squeak, ['compile_squeak'], 'XXX') + def task_source_js(self): + from pypy.translator.js.js import JS + self.gen = JS(self.translator, functions=[self.entry_point], + stackless=self.options.stackless) + filename = self.gen.write_source() + self.log.info("Wrote %s" % (filename,)) + task_source_js = taskdef(task_source_js, + ['stackcheckinsertion', 'backendopt', 'rtype'], + 'Generating Javascript source') + + def task_compile_js(self): + pass + task_compile_js = taskdef(task_compile_js, ['source_js'], + 'Skipping Javascript compilation') + + def task_run_js(self): + pass + task_run_js = taskdef(task_run_js, ['compile_js'], + 'Please manually run the generated code') + def proceed(self, goals): if not goals: if self.default_goal: Modified: pypy/dist/pypy/translator/goal/translate.py ============================================================================== --- pypy/dist/pypy/translator/goal/translate.py (original) +++ pypy/dist/pypy/translator/goal/translate.py Mon May 8 14:36:10 2006 @@ -46,7 +46,7 @@ '0_source': [OPT(('-s', '--source'), "Generate source code", GOAL), OPT(('--no-source',), "Don't generate source code", SKIP_GOAL)], - '1_backend': [OPT(('-b', '--backend'), "Backend", ['c', 'llvm', 'cl', 'squeak'])], + '1_backend': [OPT(('-b', '--backend'), "Backend", ['c', 'llvm', 'cl', 'squeak', 'js'])], '2_gc': [OPT(('--gc',), "Garbage collector", ['boehm', 'ref', 'framework', 'none', 'exact_boehm'])], '3_stackless': [OPT(('--stackless',), "Stackless code generation", True)], From ale at codespeak.net Mon May 8 15:46:18 2006 From: ale at codespeak.net (ale at codespeak.net) Date: Mon, 8 May 2006 15:46:18 +0200 (CEST) Subject: [pypy-svn] r26964 - in pypy/dist/pypy/lib/pyontology: . test Message-ID: <20060508134618.5DAE910070@code0.codespeak.net> Author: ale Date: Mon May 8 15:46:17 2006 New Revision: 26964 Modified: pypy/dist/pypy/lib/pyontology/constraint_classes.py pypy/dist/pypy/lib/pyontology/pyontology.py pypy/dist/pypy/lib/pyontology/test/test_ontology.py Log: some progress in reasoning on OWL schemas Modified: pypy/dist/pypy/lib/pyontology/constraint_classes.py ============================================================================== --- pypy/dist/pypy/lib/pyontology/constraint_classes.py (original) +++ pypy/dist/pypy/lib/pyontology/constraint_classes.py Mon May 8 15:46:17 2006 @@ -222,10 +222,11 @@ domain = domains[self.variable].getValues() vals = {} for cls, val in domain: - if vals.has_key(val): - raise ConsistencyFailure("InverseFunctionalCardinality error") - else: - vals[val] = 1 + for v in val: + if vals.has_key(v): + raise ConsistencyFailure("InverseFunctionalCardinality error") + else: + vals[v] = 1 else: return 0 @@ -243,14 +244,12 @@ """Contraint: all values must be distinct""" def narrow(self, domains): + pass """narrowing algorithm for the constraint""" - domain = domains[self.variable].getValues() - domain_dict = Linkeddict(domain) - for cls, val in domain: - if val in domain_dict: - for v in domain_dict[val]: - domain.append((cls,v)) - domains[self.variable].setValues(domain) +# domain = domains[self.variable].getValues() +# for cls, val in domain: +# for v in val: +# domains[self.variable].addValue(cls,v) class SymmetricConstraint(OwlConstraint): """Contraint: all values must be distinct""" Modified: pypy/dist/pypy/lib/pyontology/pyontology.py ============================================================================== --- pypy/dist/pypy/lib/pyontology/pyontology.py (original) +++ pypy/dist/pypy/lib/pyontology/pyontology.py Mon May 8 15:46:17 2006 @@ -1,6 +1,6 @@ from rdflib import Graph, URIRef, BNode, Literal from logilab.constraint import Repository, Solver -from logilab.constraint.fd import FiniteDomain as fd +from logilab.constraint.fd import Expression, FiniteDomain as fd from logilab.constraint.propagation import AbstractDomain, AbstractConstraint, ConsistencyFailure from constraint_classes import * import sys, py @@ -18,6 +18,7 @@ uris[v] = k Class = URIRef(u'http://www.w3.org/2002/07/owl#Class') +rdf_type = URIRef(u'http://www.w3.org/1999/02/22-rdf-syntax-ns#type') rdf_rest = URIRef(u'http://www.w3.org/1999/02/22-rdf-syntax-ns#rest') rdf_first = URIRef(u'http://www.w3.org/1999/02/22-rdf-syntax-ns#first') rdf_nil = URIRef(u'http://www.w3.org/1999/02/22-rdf-syntax-ns#nil') @@ -86,7 +87,10 @@ def getBases(self): return self.bases - + + def addValue(self, value): + self.values[value] = True + def getValues(self): return self.values.keys() @@ -112,11 +116,7 @@ def getValues(self): items = self._dict.items() - res = [] - for k,v in items: - for i in v: - res.append((k,i)) - return res + return items def addValue(self, key, val): self._dict.setdefault(key, []) @@ -193,7 +193,6 @@ """ def __init__(self, name='', values=[], bases = []): ClassDomain.__init__(self, name, values, bases) - self.constraint = RestrictionConstraint(name) self.property = None builtin_voc = { @@ -245,13 +244,13 @@ def attach_fd(self): for (s, p, o) in (self.graph.triples((None,)*3)): - if (s, p, o) in self.seen.keys(): - continue - self.seen[(s, p, o)] = True self.consider_triple((s, p, o)) assert len(list(self.graph.triples((None,)*3))) == len(self.seen.keys()) def consider_triple(self,(s, p, o)): + if (s, p, o) in self.seen.keys(): + return + self.seen[(s, p, o)] = True if p.find('#') != -1: ns, func = p.split('#') else: @@ -270,12 +269,43 @@ propdom = self.variables[avar] res = propdom.addValue(sub, obj) + def resolve_item(self, item): + item_as_subject = self.graph.triples((item, None, None)) + for triple in item_as_subject: + self.consider_triple(triple) + + def get_individuals_of(self, item): + item_as_subject = self.graph.triples(( None, rdf_type, item)) + for triple in item_as_subject: + self.consider_triple(triple) + + def make_var(self, cls=fd, a=''): + if type(a) == URIRef: + if a.find('#') != -1: + ns,name = a.split('#') + else: + ns,name = a,'' + if ns not in uris.keys(): + uris[ns] = ns.split('/')[-1] + a = uris[ns] + '_' + name + var = str(a.replace('-','_')) + else: + var = a + if not cls: + return var + if not var in self.variables: + self.variables[var] = cls(var) + elif type(self.variables[var]) in cls.__bases__: + vals = self.variables[var].getValues() + self.variables[var] = cls(var) + self.variables[var].setValues(vals) + return var + def evaluate(self, terms): # terms is a dictionary of types of restriction and list of values for this restriction - term = terms['Cardinality'] - if len(term) < 1: return + term = terms + if len(term) < 1: return mini = maxi = equal = None - for tp,val in term: if tp == '<': if not maxi or val < maxi : maxi = val @@ -294,8 +324,8 @@ def check_TBoxes(self): for var, cls in self.variables.items(): for prop, terms in cls.TBox.items(): - if len(terms) > 1: - self.evaluate(terms) + if len(terms['Cardinality']) > 1: + self.evaluate(terms['Cardinality']) def solve(self,verbose=0): rep = Repository(self.variables.keys(), self.variables, self.constraints) @@ -327,52 +357,19 @@ self.variables[avar].setValues(res) return avar - def resolve_item(self, item): - item_as_subject = self.graph.triples((item, None, None)) - for triple in item_as_subject: - if triple in self.seen.keys(): - continue - self.seen[triple] = True - self.consider_triple(triple) - - def make_var(self, cls=fd, a=''): - self.resolve_item(a) - if type(a) == URIRef: - if a.find('#') != -1: - ns,name = a.split('#') - else: - ns,name = a,'' - if ns not in uris.keys(): - uris[ns] = ns.split('/')[-1] - a = uris[ns] + '_' + name - var = str(a.replace('-','_')) - else: - var = a - if not cls: - return var - if not var in self.variables: - self.variables[var] = cls(var) - elif type(self.variables[var]) in cls.__bases__: - vals = self.variables[var].getValues() - self.variables[var] = cls(var) - self.variables[var].setValues(vals) - return var - #---------------- Implementation ---------------- def comment(self, s, var): pass def type(self, s, var): + avar = self.make_var(ClassDomain, var) if not var in builtin_voc : # var is not one of the builtin classes - avar = self.make_var(ClassDomain, var) svar = self.make_var(self.variables[avar].__class__, s) - constrain = TypeConstraint(svar, avar) - self.constraints.append(constrain) else: # var is a builtin class - cls =builtin_voc[var] + cls = builtin_voc[var] if cls == List: return else: @@ -383,6 +380,7 @@ cls = self.variables[svar] if hasattr(cls, 'constraint'): self.constraints.append(cls.constraint) + self.variables[avar].addValue(svar) def first(self, s, var): pass @@ -393,8 +391,8 @@ def onProperty(self, s, var): svar =self.make_var(Restriction, s) avar =self.make_var(Property, var) - self.variables[svar].property = avar - + restr = self.variables[svar] + restr.property = avar #---Class Axioms---#000000#FFFFFF----------------------------------------------- @@ -404,22 +402,28 @@ # class extension of var, ie if a indiviual is in # the extension of s it must be in the extension of # var + self.resolve_item(s) + self.resolve_item(var) avar = self.make_var(None, var) svar = self.make_var(ClassDomain, s) obj = self.variables[avar] sub = self.variables[svar] + if obj.TBox: - sub.TBox.setdefault(obj.property, {}) - op = sub.TBox[obj.property] - for restr in obj.TBox.keys(): - op.setdefault(restr,[]) - op[restr].extend(obj.TBox[restr]) - - assert len(sub.TBox) > 0 -# self.variables.pop(avar) - cons = SubClassConstraint( svar, avar) - self.constraints.append(cons) - + for key in obj.TBox.keys(): + sub.TBox.setdefault(key,{}) + prop = sub.TBox[key] + for typ in obj.TBox[key].keys(): + prop.setdefault(typ, []) + prop[typ].extend(obj.TBox[key][typ]) + +# if isinstance(self.variables[avar], Restriction): +# self.variables.pop(avar) + else: + cons = SubClassConstraint( svar, avar) + self.constraints.append(cons) + self.get_individuals_of(var) + def equivalentClass(self, s, var): self.subClassOf(s, var) self.subClassOf(var, s) @@ -507,43 +511,66 @@ def maxCardinality(self, s, var): """ Len of finite domain of the property shall be less than or equal to var""" + self.resolve_item(s) svar =self.make_var(Restriction, s) - constrain = MaxCardinality(svar, int(var)) + cls = list(self.graph.subjects(None,s))[0] + cls_name = self.make_var(ClassDomain, cls) + prop = self.variables[svar].property + self.variables[svar].TBox[prop] = {'Cardinality': [( '<', int(var))]} + formula = "not isinstance(%s[0], self.variables[%s]) or len(%s[1] < int(%s))" %(prop, cls_name, prop, var) + constrain = Expression([prop], formula) self.constraints.append(constrain) - self.variables[svar].TBox['Cardinality'] = [( '>', int(var))] - + def minCardinality(self, s, var): """ Len of finite domain of the property shall be greater than or equal to var""" + self.resolve_item(s) svar =self.make_var(Restriction, s) - constrain = MinCardinality(svar, int(var)) + cls = list(self.graph.subjects(None,s))[0] + cls_name = self.make_var(ClassDomain, cls) + prop = self.variables[svar].property + self.variables[svar].TBox[prop] = {'Cardinality': [( '>', int(var))]} + formula = "not isinstance(%s[0], self.variables[%s]) or len(%s[1] > int(%s))" %(prop, cls_name, prop, var) + constrain = Expression([prop], formula) self.constraints.append(constrain) - self.variables[svar].TBox['Cardinality'] = [( '>', int(var))] def cardinality(self, s, var): """ Len of finite domain of the property shall be equal to var""" + self.resolve_item(s) svar =self.make_var(Restriction, s) - # Check if var is an int, else find the int buried in the structure - constrain = Cardinality(svar, int(var)) + cls = list(self.graph.subjects(None,s))[0] + cls_name = self.make_var(ClassDomain, cls) + prop = self.variables[svar].property + self.variables[svar].TBox[prop] = {'Cardinality': [( '=', int(var))]} + formula = "not isinstance(%s[0], self.variables[%s]) or len(%s[1] == int(%s))" %(prop, cls_name, prop, var) + constrain = Expression([prop], formula) self.constraints.append(constrain) - self.variables[svar].TBox['Cardinality'] = [( '=', int(var))] def hasValue(self, s, var): + self.resolve_item(var) svar = self.make_var(Restriction, s) avar = self.make_var(None, var) - constrain = HasvalueConstraint(svar, avar) - self.constraints.append(constrain) + restr = self.variables[svar] + restr.TBox['hasValue'] = [('hasvalue', var)] +# constrain = HasvalueConstraint(svar, avar) +# self.constraints.append(constrain) def allValuesFrom(self, s, var): + self.resolve_item(var) svar = self.make_var(Restriction, s) avar = self.make_var(None, var) - constrain = AllValueConstraint(svar, avar) - self.constraints.append(constrain) + restr = self.variables[svar] + restr.TBox['allValues'] = [('allvalue', var)] +# constrain = AllValueConstraint(svar, avar) +# self.constraints.append(constrain) def someValuesFrom(self, s, var): + self.resolve_item(var) svar = self.make_var(Restriction, s) avar = self.make_var(None, var) - constrain = SomeValueConstraint(svar, avar) - self.constraints.append(constrain) + restr = self.variables[svar] + restr.TBox['someValues'] = [('somevalues', var)] +# constrain = SomeValueConstraint(svar, avar) +# self.constraints.append(constrain) # ----------------- ---------------- Modified: pypy/dist/pypy/lib/pyontology/test/test_ontology.py ============================================================================== --- pypy/dist/pypy/lib/pyontology/test/test_ontology.py (original) +++ pypy/dist/pypy/lib/pyontology/test/test_ontology.py Mon May 8 15:46:17 2006 @@ -48,16 +48,16 @@ O.type(a,obj) O.consistency() O.consistency() - assert len(O.variables) == 3 + assert len(O.variables) == 4 assert 'C_' in O.variables['A_'].getValues() def test_addvalue(): O = Ontology() a = O.make_var(Property, 'a') O.variables[a].addValue('key', 42) - assert O.variables[a].getValues() == [('key', 42)] + assert O.variables[a].getValues() == [('key', [42])] O.variables[a].addValue('key', 43) - assert O.variables[a].getValues() == [('key', 42),('key',43)] + assert O.variables[a].getValues() == [('key', [42, 43])] def no_test_ClassDomain(): a = ClassDomain() @@ -255,7 +255,7 @@ py.test.raises(ConsistencyFailure, O.consistency) def test_Transitiveproperty(): - + py.test.skip("in transit") O = Ontology() #Make functional property sub = URIRef('subRegionOf') @@ -275,9 +275,10 @@ O.type(sub, obj) O.variables['subRegionOf_'].setValues([('Italy_','Tuscanny_'),('Tuscanny_','Chianti_')]) O.consistency() - assert ('Italy_', 'Chianti_') in O.variables['subRegionOf_'].getValues() + assert ('Italy_', ['Chianti_']) in O.variables['subRegionOf_'].getValues() def test_symmetricproperty(): + py.test.skip("in transit") O = Ontology() #Make functional property @@ -300,6 +301,7 @@ assert ('Alice_', 'Bob_') in O.variables['friend_'].getValues() def test_inverseof(): + py.test.skip("in transit") O = Ontology() own = URIRef('owner') obj = URIRef(namespaces['owl']+'#ObjectProperty') @@ -325,15 +327,16 @@ O.consistency() def test_hasvalue(): + py.test.skip("in transit") O = Ontology() restrict = BNode('anon1') obj = URIRef(namespaces['owl']+'#Restriction') O.type(restrict, obj) p = URIRef('p') - O.onProperty(restrict,p) obj = URIRef(namespaces['owl']+'#ObjectProperty') O.type(p, obj) O.hasValue(restrict, 2) + O.onProperty(restrict,p) cls = URIRef('class') obj = URIRef(namespaces['owl']+'#Class') O.type(cls, obj) @@ -378,6 +381,7 @@ assert set(O.rep._domains[restrict].getValues()) == set(own) def test_somevaluesfrom_datarange(): + py.test.skip("in flux") O = Ontology() datarange = BNode('anon') own = ['1','2','3'] @@ -387,10 +391,10 @@ obj = URIRef(namespaces['owl']+'#Restriction') O.type(restrict, obj) p = URIRef('p') - O.onProperty(restrict,p) obj = URIRef(namespaces['owl']+'#ObjectProperty') O.type(p, obj) O.someValuesFrom(restrict, datarange) + O.onProperty(restrict,p) cls = URIRef('class') obj = URIRef(namespaces['owl']+'#Class') O.type(cls, obj) @@ -399,6 +403,7 @@ py.test.raises(ConsistencyFailure, O.consistency) def test_allvaluesfrom_datarange(): + py.test.skip("in flux") O = Ontology() datarange = BNode('anon') own = ['1','2','3'] @@ -408,10 +413,10 @@ obj = URIRef(namespaces['owl']+'#Restriction') O.type(restrict, obj) p = URIRef('p') - O.onProperty(restrict,p) obj = URIRef(namespaces['owl']+'#ObjectProperty') O.type(p, obj) O.allValuesFrom(restrict, datarange) + O.onProperty(restrict,p) cls = URIRef('class') obj = URIRef(namespaces['owl']+'#Class') O.type(cls, obj) @@ -482,7 +487,7 @@ O.type(sub, obj) O.variables[O.make_var(None,sub)].setValues([(cls,'1')]) O.consistency(3) - assert ('liist1','1') in O.rep._domains[O.make_var(None,sub)].getValues() + assert ('liist1',['1']) in O.rep._domains[O.make_var(None,sub)].getValues() def test_sameasconsistency(): O = Ontology() @@ -505,28 +510,53 @@ # 'cls' by subclassing two maxCardinality restrictions becomes the set of # individuals satisfying both restriction, ie having exactly 2 values of # predicate p - + cls = URIRef('cls') O = Ontology() - cls = O.make_var(ClassDomain,URIRef('cls')) - O.type(cls, namespaces['owl']+'#Class') - + O.add((cls, namespaces['rdfs']+'#type', namespaces['owl']+'#Class' )) p = O.make_var(Property,URIRef('p')) - O.type(p, namespaces['owl']+'#ObjectProperty') + p = URIRef('p') + O.add((p, namespaces['rdfs']+'#type', namespaces['owl']+'#ObjectProperty' )) - restr = O.make_var(Restriction,BNode('anon')) - O.subClassOf(cls, restr) - O.maxCardinality(restr, 2) - O.type(restr, namespaces['owl']+'#Restriction') - O.onProperty(restr, p) + restr = BNode('anon') + O.add((restr, namespaces['rdfs']+'#type', namespaces['owl']+'#Restriction' )) + O.add((restr, namespaces['rdfs']+'#onProperty', p )) + O.add((cls, namespaces['rdfs']+'#subClassOf',restr )) + O.add((restr, namespaces['rdfs']+'#maxCardinality', 2 )) restr2 = BNode('anon2') - O.type(restr2, namespaces['owl']+'#Restriction') - O.onProperty(restr2, p) - O.subClassOf(cls, restr2) - O.minCardinality(restr2, 3) - constraints = len(O.constraints) - py.test.raises(ConsistencyFailure, O.consistency, 3) + O.add((restr2, namespaces['rdfs']+'#type', namespaces['owl']+'#Restriction' )) + O.add((restr2, namespaces['rdfs']+'#onProperty', p )) + O.add((cls, namespaces['rdfs']+'#subClassOf',restr2 )) + O.add((restr2, namespaces['rdfs']+'#minCardinality', 3 )) + O.attach_fd() + py.test.raises(ConsistencyFailure, O.check_TBoxes) + +def test_subclassof_cardinality(): + cls = URIRef('cls') + cls2 = URIRef('cls2') + O = Ontology() + O.add((cls, namespaces['rdfs']+'#type', namespaces['owl']+'#Class' )) + O.add((cls2, namespaces['rdfs']+'#type', namespaces['owl']+'#Class' )) + p = O.make_var(Property,URIRef('p')) + p = URIRef('p') + O.add((p, namespaces['rdfs']+'#type', namespaces['owl']+'#ObjectProperty' )) + + restr = BNode('anon') + O.add((restr, namespaces['rdfs']+'#type', namespaces['owl']+'#Restriction' )) + O.add((restr, namespaces['rdfs']+'#onProperty', p )) + O.add((cls, namespaces['rdfs']+'#subClassOf',restr )) + O.add((restr, namespaces['rdfs']+'#maxCardinality', 2 )) + restr2 = BNode('anon2') + O.add((restr2, namespaces['rdfs']+'#type', namespaces['owl']+'#Restriction' )) + O.add((restr2, namespaces['rdfs']+'#onProperty', p )) + O.add((cls, namespaces['rdfs']+'#subClassOf',restr2 )) + O.add((restr2, namespaces['rdfs']+'#minCardinality', 3 )) + O.add((cls2, namespaces['rdfs']+'#subClassOf', cls )) + O.attach_fd() + py.test.raises(ConsistencyFailure, O.check_TBoxes) + assert O.variables['cls_'].TBox == O.variables['cls2_'].TBox + def test_add_file(): O = Ontology() O.add_file('premises001.rdf') @@ -551,3 +581,12 @@ O.check_TBoxes() lll = len(O.variables) assert len(list(O.graph.triples((None,)*3))) > l + +def test_allvalues_file(): + O = Ontology() + O.add_file('approved/allValuesfrom/premises002.rdf') + print list(O.graph.triples((None,)*3)) + #O = Ontology() + O.add_file('approved/allValuesfrom/nonconclusions002.rdf') + print list(O.graph.triples((None,)*3)) + assert 1 \ No newline at end of file From arigo at codespeak.net Mon May 8 17:29:19 2006 From: arigo at codespeak.net (arigo at codespeak.net) Date: Mon, 8 May 2006 17:29:19 +0200 (CEST) Subject: [pypy-svn] r26969 - in pypy/dist/pypy: rpython rpython/lltypesystem translator/stackless Message-ID: <20060508152919.109EA10061@code0.codespeak.net> Author: arigo Date: Mon May 8 17:29:17 2006 New Revision: 26969 Modified: pypy/dist/pypy/rpython/llinterp.py pypy/dist/pypy/rpython/lltypesystem/lltype.py pypy/dist/pypy/rpython/rbuiltin.py pypy/dist/pypy/translator/stackless/code.py pypy/dist/pypy/translator/stackless/transform.py Log: (pedronis, arigo) Stackless transform: type erasure in a GC-friendly way, with GcOpaqueType. Added some comments, changed some strange usages of numbers into strange usages of globals() in a very Pythonic way, etc. Modified: pypy/dist/pypy/rpython/llinterp.py ============================================================================== --- pypy/dist/pypy/rpython/llinterp.py (original) +++ pypy/dist/pypy/rpython/llinterp.py Mon May 8 17:29:17 2006 @@ -333,10 +333,10 @@ elif operation.opname == 'indirect_call': assert isinstance(operation.args[0], Variable) vals = [self.getval(x) for x in operation.args] - # if these special cases pile up, do something better here + # XXX these special cases DO pile up, do something better here if operation.opname in ['cast_pointer', 'ooupcast', 'oodowncast', 'cast_adr_to_ptr', 'cast_int_to_ptr', - 'cast_opaque_ptr']: + 'cast_opaque_ptr', 'unsafe_call']: vals.insert(0, operation.result.concretetype) try: retval = ophandler(*vals) @@ -479,7 +479,7 @@ log.warn("op_indirect_call with graphs=None:", f) return self.op_direct_call(f, *args) - def op_unsafe_call(self, f): + def op_unsafe_call(self, TGT, f): assert isinstance(f, llmemory.fakeaddress) assert f.offset is None obj = self.llinterpreter.typer.type_system.deref(f.ob) @@ -490,9 +490,7 @@ args.append(arg.concretetype._defl()) frame = self.__class__(graph, args, self.llinterpreter, self) result = frame.eval() - if isinstance(lltype.typeOf(result), lltype.Ptr): - result = llmemory.cast_ptr_to_adr(result) - return result + return lltype._cast_whatever(TGT, result) def op_malloc(self, obj): if self.llinterpreter.gc is not None: Modified: pypy/dist/pypy/rpython/lltypesystem/lltype.py ============================================================================== --- pypy/dist/pypy/rpython/lltypesystem/lltype.py (original) +++ pypy/dist/pypy/rpython/lltypesystem/lltype.py Mon May 8 17:29:17 2006 @@ -580,7 +580,28 @@ if cast is None: raise TypeError, "unsupported cast" return cast(value) - + +def _cast_whatever(TGT, value): + from pypy.rpython.lltypesystem import llmemory + ORIG = typeOf(value) + if ORIG == TGT: + return value + if (isinstance(TGT, Primitive) and + isinstance(ORIG, Primitive)): + return cast_primitive(TGT, value) + elif isinstance(TGT, Ptr): + if isinstance(ORIG, Ptr): + if (isinstance(TGT.TO, OpaqueType) or + isinstance(ORIG.TO, OpaqueType)): + return cast_opaque_ptr(TGT, value) + else: + return cast_pointer(TGT, value) + elif ORIG == llmemory.Address: + return llmemory.cast_adr_to_ptr(value, TGT) + elif TGT == llmemory.Address and isinstance(ORIG, Ptr): + return llmemory.cast_ptr_to_adr(value) + raise TypeError("don't know how to cast from %r to %r" % (ORIG, TGT)) + class InvalidCast(TypeError): pass Modified: pypy/dist/pypy/rpython/rbuiltin.py ============================================================================== --- pypy/dist/pypy/rpython/rbuiltin.py (original) +++ pypy/dist/pypy/rpython/rbuiltin.py Mon May 8 17:29:17 2006 @@ -399,7 +399,12 @@ return v_value elif isinstance(TGT, lltype.Ptr): if isinstance(ORIG, lltype.Ptr): - return llops.genop('cast_pointer', [v_value], resulttype = TGT) + if (isinstance(TGT.TO, lltype.OpaqueType) or + isinstance(ORIG.TO, lltype.OpaqueType)): + return llops.genop('cast_opaque_ptr', [v_value], + resulttype = TGT) + else: + return llops.genop('cast_pointer', [v_value], resulttype = TGT) elif ORIG == llmemory.Address: return llops.genop('cast_adr_to_ptr', [v_value], resulttype = TGT) elif TGT == llmemory.Address and isinstance(ORIG, lltype.Ptr): Modified: pypy/dist/pypy/translator/stackless/code.py ============================================================================== --- pypy/dist/pypy/translator/stackless/code.py (original) +++ pypy/dist/pypy/translator/stackless/code.py Mon May 8 17:29:17 2006 @@ -2,9 +2,29 @@ from pypy.rpython import rarithmetic from pypy.rpython import extfunctable +SAVED_REFERENCE = lltype.Ptr(lltype.GcOpaqueType('stackless.saved_ref')) +null_saved_ref = lltype.nullptr(SAVED_REFERENCE.TO) -def ll_frame_switch(state): +STORAGE_TYPES = [lltype.Void, SAVED_REFERENCE, llmemory.Address, + lltype.Signed, lltype.Float, lltype.SignedLongLong] + +STORAGE_FIELDS = {SAVED_REFERENCE: 'ref', + llmemory.Address: 'addr', + lltype.Signed: 'long', + lltype.Float: 'float', + lltype.SignedLongLong: 'longlong', + } + +RETVAL_VOID = 0 +for _key, _value in STORAGE_FIELDS.items(): + globals()['RETVAL_' + _value.upper()] = STORAGE_TYPES.index(_key) + +# ____________________________________________________________ + +def ll_frame_switch(targetstate): if global_state.restart_substate == 0: + # normal entry point for a call to state.switch() + # first unwind the stack u = UnwindException() s = lltype.malloc(SWITCH_STATE) s.header.restartstate = 1 @@ -12,26 +32,35 @@ f = ll_frame_switch if global_state.restart_substate: f = None - s.c = llmemory.cast_ptr_to_adr(state) + s.c = lltype.cast_opaque_ptr(SAVED_REFERENCE, targetstate) s.header.function = llmemory.cast_ptr_to_adr(f) + s.header.retval_type = RETVAL_REF add_frame_state(u, s.header) raise u elif global_state.restart_substate == 1: + # STATE 1: we didn't do anything so far, but the stack is unwound global_state.restart_substate = 0 - top = global_state.top - s = lltype.cast_pointer(lltype.Ptr(SWITCH_STATE), top) - top.restartstate = 2 - state = llmemory.cast_adr_to_ptr(s.c, lltype.Ptr(STATE_HEADER)) - global_state.top = state - global_state.retval_void_p = llmemory.cast_ptr_to_adr(top) - raise UnwindException() + # grab the frame corresponding to ourself, and prepare it for + # the future switch() back, which will go to STATE 2 below + sourcestate = global_state.top + sourcestate.restartstate = 2 + # the 'targetstate' local is garbage here, it must be read back from + # 's.c' where we saved it by STATE 0 above + s = lltype.cast_pointer(lltype.Ptr(SWITCH_STATE), sourcestate) + targetstate = lltype.cast_opaque_ptr(lltype.Ptr(STATE_HEADER), s.c) + global_state.top = targetstate + global_state.retval_ref = lltype.cast_opaque_ptr(SAVED_REFERENCE, + sourcestate) + raise UnwindException() # this jumps to targetstate else: - top = global_state.top + # STATE 2: switching back into a tasklet suspended by + # a call to switch() global_state.top = null_state global_state.restart_substate = 0 - origin_state = llmemory.cast_adr_to_ptr(fetch_retval_void_p(), - OPAQUE_STATE_HEADER_PTR) - return origin_state + origin_state = lltype.cast_opaque_ptr(OPAQUE_STATE_HEADER_PTR, + fetch_retval_ref()) + return origin_state # a normal return into the current tasklet, + # with the source state as return value ll_frame_switch.stackless_explicit = True STATE_HEADER = lltype.GcStruct('state_header', @@ -55,10 +84,12 @@ SWITCH_STATE = lltype.GcStruct('state_switch', ('header', STATE_HEADER), - ('c', llmemory.Address)) + ('c', SAVED_REFERENCE)) def yield_current_frame_to_caller(): if global_state.restart_substate == 0: + # normal entry point for yield_current_frame_to_caller() + # first unwind the stack u = UnwindException() s = lltype.malloc(STATE_HEADER) s.restartstate = 1 @@ -67,45 +98,50 @@ if global_state.restart_substate: f = None s.function = llmemory.cast_ptr_to_adr(f) - s.retval_type = RETVAL_VOID_P + s.retval_type = RETVAL_REF add_frame_state(u, s) - raise u + raise u # this goes to 'STATE 1' below + elif global_state.restart_substate == 1: + # STATE 1: we didn't do anything so far, but the stack is unwound global_state.restart_substate = 0 ycftc_state = global_state.top - ycftc_state.restartstate = 2 our_caller_state = ycftc_state.f_back caller_state = our_caller_state.f_back # the next three lines are pure rtyper-pleasing hacks f = yield_current_frame_to_caller if global_state.restart_substate: f = None + # when our immediate caller finishes (which is later, when the + # tasklet finishes), then we will jump to 'STATE 2' below endstate = lltype.malloc(STATE_HEADER) - endstate.restartstate = 3 + endstate.restartstate = 2 endstate.function = llmemory.cast_ptr_to_adr(f) our_caller_state.f_back = endstate global_state.top = caller_state - global_state.retval_void_p = llmemory.cast_ptr_to_adr(ycftc_state) - raise UnwindException() - elif global_state.restart_substate == 2: - top = global_state.top - global_state.top = null_state - global_state.restart_substate = 0 - origin_state = llmemory.cast_adr_to_ptr(fetch_retval_void_p(), - OPAQUE_STATE_HEADER_PTR) - return origin_state + global_state.retval_ref = lltype.cast_opaque_ptr(SAVED_REFERENCE, + our_caller_state) + raise UnwindException() # this goes to the caller's caller + else: + # STATE 2: this is a slight abuse of yield_current_frame_to_caller(), + # as we return here when our immediate caller returns (and thus the + # new tasklet finishes). global_state.restart_substate = 0 - next_state = llmemory.cast_adr_to_ptr(fetch_retval_void_p(), - lltype.Ptr(STATE_HEADER)) + next_state = lltype.cast_opaque_ptr(lltype.Ptr(STATE_HEADER), + fetch_retval_ref()) + # return a NULL state pointer to the target of the implicit switch global_state.top = next_state - global_state.retval_void_p = llmemory.NULL - raise UnwindException() + global_state.retval_ref = null_saved_ref + raise UnwindException() # this goes to the switch target given by + # the 'return' at the end of our caller yield_current_frame_to_caller.stackless_explicit = True def stack_frames_depth(): if not global_state.restart_substate: + # normal entry point for stack_frames_depth() + # first unwind the stack u = UnwindException() s = lltype.malloc(STATE_HEADER) s.restartstate = 1 @@ -116,8 +152,10 @@ s.function = llmemory.cast_ptr_to_adr(f) s.retval_type = RETVAL_LONG add_frame_state(u, s) - raise u + raise u # goes to STATE 1 below else: + # STATE 1: now the stack is unwound, and we can count the frames + # in the heap cur = global_state.top global_state.restart_substate = 0 depth = 0 @@ -129,6 +167,8 @@ def ll_stack_unwind(): if not global_state.restart_substate: + # normal entry point for stack_frames_depth() + # first unwind the stack in the usual way u = UnwindException() s = lltype.malloc(STATE_HEADER) s.restartstate = 1 @@ -139,8 +179,10 @@ s.function = llmemory.cast_ptr_to_adr(f) s.retval_type = RETVAL_VOID add_frame_state(u, s) - raise u + raise u # goes to STATE 1 below else: + # STATE 1: now the stack is unwound. That was the goal. + # Return to caller. global_state.restart_substate = 0 ll_stack_unwind.stackless_explicit = True @@ -151,29 +193,30 @@ self.retval_long = 0 self.retval_longlong = rarithmetic.r_longlong(0) self.retval_float = 0.0 - self.retval_void_p = llmemory.NULL + self.retval_addr = llmemory.NULL + self.retval_ref = null_saved_ref self.exception = None global_state = StacklessData() -RETVAL_VOID, RETVAL_LONG, RETVAL_LONGLONG, RETVAL_FLOAT, RETVAL_VOID_P = \ - range(5) - def call_function(fn, retval_code): if retval_code == RETVAL_VOID: lloperation.llop.unsafe_call(lltype.Void, fn) + elif retval_code == RETVAL_REF: + global_state.retval_ref = lloperation.llop.unsafe_call( + SAVED_REFERENCE, fn) + elif retval_code == RETVAL_ADDR: + global_state.retval_addr = lloperation.llop.unsafe_call( + llmemory.Address, fn) elif retval_code == RETVAL_LONG: global_state.retval_long = lloperation.llop.unsafe_call( lltype.Signed, fn) - elif retval_code == RETVAL_LONGLONG: - global_state.retval_longlong = lloperation.llop.unsafe_call( - lltype.SignedLongLong, fn) elif retval_code == RETVAL_FLOAT: global_state.retval_float = lloperation.llop.unsafe_call( lltype.Float, fn) - elif retval_code == RETVAL_VOID_P: - global_state.retval_void_p = lloperation.llop.unsafe_call( - llmemory.Address, fn) + elif retval_code == RETVAL_LONGLONG: + global_state.retval_longlong = lloperation.llop.unsafe_call( + lltype.SignedLongLong, fn) call_function.stackless_explicit = True class UnwindException(lloperation.StackException): @@ -274,11 +317,24 @@ return global_state.retval_float fetch_retval_float.stackless_explicit = True -def fetch_retval_void_p(): +def fetch_retval_addr(): + e = global_state.exception + if e: + global_state.exception = None + raise e + else: + res = global_state.retval_addr + global_state.retval_addr = llmemory.NULL + return res +fetch_retval_addr.stackless_explicit = True + +def fetch_retval_ref(): e = global_state.exception if e: global_state.exception = None raise e else: - return global_state.retval_void_p -fetch_retval_void_p.stackless_explicit = True + res = global_state.retval_ref + global_state.retval_ref = null_saved_ref + return res +fetch_retval_ref.stackless_explicit = True Modified: pypy/dist/pypy/translator/stackless/transform.py ============================================================================== --- pypy/dist/pypy/translator/stackless/transform.py (original) +++ pypy/dist/pypy/translator/stackless/transform.py Mon May 8 17:29:17 2006 @@ -6,7 +6,9 @@ from pypy.translator import unsimplify from pypy.annotation import model as annmodel from pypy.rpython.annlowlevel import MixLevelHelperAnnotator -from pypy.translator.stackless import code +from pypy.translator.stackless import code +from pypy.translator.stackless.code import SAVED_REFERENCE, STORAGE_TYPES +from pypy.translator.stackless.code import STORAGE_FIELDS from pypy.rpython.rclass import getinstancerepr from pypy.rpython.rbuiltin import gen_cast from pypy.rpython.rtyper import LowLevelOpList @@ -14,28 +16,24 @@ from pypy.translator.stackless.code import STATE_HEADER, null_state -STORAGE_TYPES = [llmemory.Address, - lltype.Signed, - lltype.Float, - lltype.SignedLongLong] -STORAGE_FIELDS = ['addr', - 'long', - 'float', - 'longlong'] - def storage_type(T): - """Return the index into STORAGE_TYPES + """Return the 'erased' storage type corresponding to T. """ if T is lltype.Void: - return None + return lltype.Void + elif isinstance(T, lltype.Ptr): + if T._needsgc(): + return SAVED_REFERENCE + else: + return llmemory.Address elif T is lltype.Float: - return 2 + return lltype.Float elif T in [lltype.SignedLongLong, lltype.UnsignedLongLong]: - return 3 - elif T is llmemory.Address or isinstance(T, lltype.Ptr): - return 0 + return lltype.SignedLongLong + elif T is llmemory.Address: + return lltype.Address elif isinstance(T, lltype.Primitive): - return 1 + return lltype.Signed else: raise Exception("don't know about %r" % (T,)) @@ -107,16 +105,20 @@ self.resume_state_ptr = mixlevelannotator.constfunc( code.resume_state, [], annmodel.SomeInteger()) - self.fetch_retval_void_ptr = mixlevelannotator.constfunc( - code.fetch_retval_void, [], annmodel.s_None) - self.fetch_retval_long_ptr = mixlevelannotator.constfunc( - code.fetch_retval_long, [], annmodel.SomeInteger()) - self.fetch_retval_longlong_ptr = mixlevelannotator.constfunc( - code.fetch_retval_longlong, [], annmodel.SomeInteger(size=2)) - self.fetch_retval_float_ptr = mixlevelannotator.constfunc( - code.fetch_retval_float, [], annmodel.SomeFloat()) - self.fetch_retval_void_p_ptr = mixlevelannotator.constfunc( - code.fetch_retval_void_p, [], annmodel.SomeAddress()) + self.fetch_retvals = { + lltype.Void: mixlevelannotator.constfunc( + code.fetch_retval_void, [], annmodel.s_None), + lltype.Signed: mixlevelannotator.constfunc( + code.fetch_retval_long, [], annmodel.SomeInteger()), + lltype.SignedLongLong: mixlevelannotator.constfunc( + code.fetch_retval_longlong, [], annmodel.SomeInteger(size=2)), + lltype.Float: mixlevelannotator.constfunc( + code.fetch_retval_float, [], annmodel.SomeFloat()), + llmemory.Address: mixlevelannotator.constfunc( + code.fetch_retval_addr, [], annmodel.SomeAddress()), + SAVED_REFERENCE: mixlevelannotator.constfunc( + code.fetch_retval_ref, [], annmodel.SomePtr(SAVED_REFERENCE)), + } s_StatePtr = annmodel.SomePtr(code.OPAQUE_STATE_HEADER_PTR) self.suggested_primitives = { @@ -145,25 +147,24 @@ def frame_type_for_vars(self, vars): fieldnames = [] - counts = [0] * len(STORAGE_TYPES) + counts = {} for v in vars: t = storage_type(v.concretetype) - if t is None: + if t is lltype.Void: fieldnames.append(None) else: - fieldnames.append('state_%s_%d' % (STORAGE_FIELDS[t], - counts[t])) - counts[t] = counts[t] + 1 - key = tuple(counts) + n = counts.get(t, 0) + fieldnames.append('state_%s_%d' % (STORAGE_FIELDS[t], n)) + counts[t] = n + 1 + key = lltype.frozendict(counts) if key in self.frametypes: T = self.frametypes[key] else: fields = [] - for t in range(len(STORAGE_TYPES)): - for j in range(counts[t]): - fields.append(('state_%s_%d'%(STORAGE_FIELDS[t], j), - STORAGE_TYPES[t])) - T = lltype.GcStruct("FrameState_%d_%d_%d_%d" % tuple(key), + for t in STORAGE_TYPES: + for j in range(counts.get(t, 0)): + fields.append(('state_%s_%d' % (STORAGE_FIELDS[t], j), t)) + T = lltype.GcStruct("FrameState", ('header', STATE_HEADER), *fields) self.frametypes[key] = T @@ -244,36 +245,16 @@ for i, arg in enumerate(resume_point.args): assert arg is not resume_point.var_result t = storage_type(arg.concretetype) - if t is None: + if t is lltype.Void: continue fname = model.Constant(resume_point.fieldnames[i], lltype.Void) v_newarg = llops.genop('getfield', [frame_top, fname], - resulttype = STORAGE_TYPES[t]) + resulttype = t) v_newarg = gen_cast(llops, arg.concretetype, v_newarg) varmap[arg] = v_newarg - r = storage_type(resume_point.var_result.concretetype) - if r is not None: - rettype = STORAGE_TYPES[r] - else: - rettype = lltype.Void - - if rettype == lltype.Signed: - getretval = self.fetch_retval_long_ptr - if rettype == lltype.SignedLongLong: - getretval = self.fetch_retval_longlong_ptr - elif rettype == lltype.Void: - getretval = self.fetch_retval_void_ptr - elif rettype == lltype.Float: - getretval = self.fetch_retval_float_ptr - elif rettype == llmemory.Address: -## if resume_point.var_result.concretetype is not \ -## llmemory.Address: -## if resume_point.var_result in \ -## resume_point.links_to_resumption[0].args: -## need_address_conversion = True - getretval = self.fetch_retval_void_p_ptr - + rettype = storage_type(resume_point.var_result.concretetype) + getretval = self.fetch_retvals[rettype] retval = llops.genop("direct_call", [getretval], resulttype = rettype) varmap[resume_point.var_result] = retval @@ -476,12 +457,8 @@ model.Constant(llmemory.fakeaddress(funcptr), llmemory.Address)], varoftype(lltype.Void))) rettype = lltype.typeOf(funcptr).TO.RESULT - retval_type = {None: code.RETVAL_VOID, - 0: code.RETVAL_VOID_P, - 1: code.RETVAL_LONG, - 2: code.RETVAL_FLOAT, - 3: code.RETVAL_LONGLONG}[storage_type(rettype)] - + retval_type = STORAGE_TYPES.index(storage_type(rettype)) + saveops.append(model.SpaceOperation( "setfield", [var_header, model.Constant("retval_type", lltype.Void), model.Constant(retval_type, lltype.Signed)], @@ -509,6 +486,6 @@ if t is lltype.Void: continue fname = model.Constant(fieldnames[i], lltype.Void) - v_typeerased = gen_cast(llops, STORAGE_TYPES[t], var) + v_typeerased = gen_cast(llops, t, var) llops.genop('setfield', [frame_state_var, fname, v_typeerased]) return llops From ale at codespeak.net Mon May 8 17:59:08 2006 From: ale at codespeak.net (ale at codespeak.net) Date: Mon, 8 May 2006 17:59:08 +0200 (CEST) Subject: [pypy-svn] r26971 - in pypy/dist/pypy/lib/pyontology: . test Message-ID: <20060508155908.DAD401006D@code0.codespeak.net> Author: ale Date: Mon May 8 17:59:08 2006 New Revision: 26971 Modified: pypy/dist/pypy/lib/pyontology/constraint_classes.py pypy/dist/pypy/lib/pyontology/pyontology.py pypy/dist/pypy/lib/pyontology/test/test_ontology.py Log: a few bugfixes Modified: pypy/dist/pypy/lib/pyontology/constraint_classes.py ============================================================================== --- pypy/dist/pypy/lib/pyontology/constraint_classes.py (original) +++ pypy/dist/pypy/lib/pyontology/constraint_classes.py Mon May 8 17:59:08 2006 @@ -101,7 +101,7 @@ vals += superdom.getValues() vals += subdom.getValues() +[self.variable] superdom.setValues(vals) - + return 0 class DisjointClassConstraint(SubClassConstraint): @@ -244,23 +244,26 @@ """Contraint: all values must be distinct""" def narrow(self, domains): - pass """narrowing algorithm for the constraint""" -# domain = domains[self.variable].getValues() -# for cls, val in domain: -# for v in val: -# domains[self.variable].addValue(cls,v) + domain = domains[self.variable].getValues() + for cls, val in domain: + for v in val: + if v in domains[self.variable]._dict.keys(): + [domains[self.variable].addValue(cls,x) + for x in domains[self.variable]._dict[v]] class SymmetricConstraint(OwlConstraint): """Contraint: all values must be distinct""" def narrow(self, domains): """narrowing algorithm for the constraint""" - domain = domains[self.variable].getValues() + prop = domains[self.variable] + domain = prop.getValues() for cls, val in domain: - if not (val, cls) in domain: - domain.append((val,cls)) - domains[self.variable].setValues(domain) + for v in val: + if not v in prop._dict.keys() or not cls in prop._dict[v]: + prop.addValue(v,cls) + class InverseofConstraint(SubClassConstraint): """Contraint: all values must be distinct""" @@ -272,12 +275,14 @@ sub_domain = domains[self.variable].getValues() res = [] for cls, val in obj_domain: - if not (val,cls) in sub_domain: - raise ConsistencyFailure("Inverseof failed for (%r, %r) in %r" % + for v in val: + if not (v,cls) in sub_domain: + raise ConsistencyFailure("Inverseof failed for (%r, %r) in %r" % (val, cls, sub_domain) ) for cls, val in sub_domain: - if not (val,cls) in obj_domain: - raise ConsistencyFailure("Inverseof failed for (%r, %r) in %r" % + for v in val: + if not (val,cls) in obj_domain: + raise ConsistencyFailure("Inverseof failed for (%r, %r) in %r" % (val, cls, obj_domain)) class DifferentfromConstraint(SubClassConstraint): Modified: pypy/dist/pypy/lib/pyontology/pyontology.py ============================================================================== --- pypy/dist/pypy/lib/pyontology/pyontology.py (original) +++ pypy/dist/pypy/lib/pyontology/pyontology.py Mon May 8 17:59:08 2006 @@ -133,6 +133,14 @@ else: self._dict[k] = [ x for x in vals if x != v] + def __contains__(self, (cls, val)): + if not cls in self._dict.keys(): + return False + vals = self._dict[cls] + if val in vals: + return True + return False + class ObjectProperty(Property): pass @@ -546,29 +554,35 @@ self.constraints.append(constrain) def hasValue(self, s, var): + self.resolve_item(s) self.resolve_item(var) svar = self.make_var(Restriction, s) avar = self.make_var(None, var) + prop = self.variables[svar].property restr = self.variables[svar] - restr.TBox['hasValue'] = [('hasvalue', var)] + restr.TBox[prop] = {'hasValue' : [('hasvalue', var)]} # constrain = HasvalueConstraint(svar, avar) # self.constraints.append(constrain) def allValuesFrom(self, s, var): + self.resolve_item(s) self.resolve_item(var) svar = self.make_var(Restriction, s) avar = self.make_var(None, var) + prop = self.variables[svar].property restr = self.variables[svar] - restr.TBox['allValues'] = [('allvalue', var)] + restr.TBox[prop] = {'allValues' : [('allValues', var)]} # constrain = AllValueConstraint(svar, avar) # self.constraints.append(constrain) def someValuesFrom(self, s, var): + self.resolve_item(s) self.resolve_item(var) svar = self.make_var(Restriction, s) avar = self.make_var(None, var) + prop = self.variables[svar].property restr = self.variables[svar] - restr.TBox['someValues'] = [('somevalues', var)] + restr.TBox[prop] = {'someValues' : [('someValues', var)]} # constrain = SomeValueConstraint(svar, avar) # self.constraints.append(constrain) Modified: pypy/dist/pypy/lib/pyontology/test/test_ontology.py ============================================================================== --- pypy/dist/pypy/lib/pyontology/test/test_ontology.py (original) +++ pypy/dist/pypy/lib/pyontology/test/test_ontology.py Mon May 8 17:59:08 2006 @@ -255,7 +255,7 @@ py.test.raises(ConsistencyFailure, O.consistency) def test_Transitiveproperty(): - py.test.skip("in transit") + #py.test.skip("in transit") O = Ontology() #Make functional property sub = URIRef('subRegionOf') @@ -275,10 +275,10 @@ O.type(sub, obj) O.variables['subRegionOf_'].setValues([('Italy_','Tuscanny_'),('Tuscanny_','Chianti_')]) O.consistency() - assert ('Italy_', ['Chianti_']) in O.variables['subRegionOf_'].getValues() + assert 'Chianti_' in O.variables['subRegionOf_']._dict['Italy_'] def test_symmetricproperty(): - py.test.skip("in transit") + #py.test.skip("in transit") O = Ontology() #Make functional property @@ -298,7 +298,7 @@ O.type(sub, obj) O.variables['friend_'].setValues([('Bob_','Alice_')]) O.consistency() - assert ('Alice_', 'Bob_') in O.variables['friend_'].getValues() + assert ('Alice_', ['Bob_']) in O.variables['friend_'].getValues() def test_inverseof(): py.test.skip("in transit") @@ -505,7 +505,6 @@ def test_cardinality_terminology(): - #py.test.skip("In progress") # Modeled after one of the standard tests (approved/maxCardinality) # 'cls' by subclassing two maxCardinality restrictions becomes the set of # individuals satisfying both restriction, ie having exactly 2 values of From ale at codespeak.net Mon May 8 18:02:06 2006 From: ale at codespeak.net (ale at codespeak.net) Date: Mon, 8 May 2006 18:02:06 +0200 (CEST) Subject: [pypy-svn] r26972 - pypy/dist/pypy/lib/pyontology/test Message-ID: <20060508160206.EB6CD1006D@code0.codespeak.net> Author: ale Date: Mon May 8 18:02:05 2006 New Revision: 26972 Modified: pypy/dist/pypy/lib/pyontology/test/test_ontology.py Log: removing debug print Modified: pypy/dist/pypy/lib/pyontology/test/test_ontology.py ============================================================================== --- pypy/dist/pypy/lib/pyontology/test/test_ontology.py (original) +++ pypy/dist/pypy/lib/pyontology/test/test_ontology.py Mon May 8 18:02:05 2006 @@ -19,7 +19,7 @@ own =owllist for i,dat in enumerate(data[:-1]): next = BNode( name + str(i)) - print next,i,dat,own + next,i,dat,own ont.first(own, dat) ont.type(next, obj) ont.rest(own, next) @@ -500,7 +500,6 @@ obj = URIRef(namespaces['owl']+'#ObjectProperty') O.type(sub, obj) O.variables[O.make_var(None,sub)].setValues([(cls,'1'), (own1,'2')]) - for dom in O.variables.values() :print type(dom) py.test.raises(ConsistencyFailure, O.consistency, 3) @@ -584,8 +583,5 @@ def test_allvalues_file(): O = Ontology() O.add_file('approved/allValuesfrom/premises002.rdf') - print list(O.graph.triples((None,)*3)) - #O = Ontology() O.add_file('approved/allValuesfrom/nonconclusions002.rdf') - print list(O.graph.triples((None,)*3)) assert 1 \ No newline at end of file From arigo at codespeak.net Mon May 8 19:34:45 2006 From: arigo at codespeak.net (arigo at codespeak.net) Date: Mon, 8 May 2006 19:34:45 +0200 (CEST) Subject: [pypy-svn] r26976 - in pypy/dist/pypy/translator/stackless: . test Message-ID: <20060508173445.E8FBA1006E@code0.codespeak.net> Author: arigo Date: Mon May 8 19:34:44 2006 New Revision: 26976 Modified: pypy/dist/pypy/translator/stackless/code.py pypy/dist/pypy/translator/stackless/test/test_yield_current_frame_to_caller.py Log: (pedronis, arigo) Oups, bug fix. See comment in code. Modified: pypy/dist/pypy/translator/stackless/code.py ============================================================================== --- pypy/dist/pypy/translator/stackless/code.py (original) +++ pypy/dist/pypy/translator/stackless/code.py Mon May 8 19:34:44 2006 @@ -123,7 +123,7 @@ our_caller_state) raise UnwindException() # this goes to the caller's caller - else: + elif global_state.restart_substate == 2: # STATE 2: this is a slight abuse of yield_current_frame_to_caller(), # as we return here when our immediate caller returns (and thus the # new tasklet finishes). @@ -136,6 +136,13 @@ raise UnwindException() # this goes to the switch target given by # the 'return' at the end of our caller + else: + # STATE 3: this is never reached! But the annotator doesn't know it, + # so it makes the whole function be annotated as returning a random + # non-constant STATE_HEADER pointer. + return lltype.cast_opaque_ptr(OPAQUE_STATE_HEADER_PTR, + global_state.top) + yield_current_frame_to_caller.stackless_explicit = True def stack_frames_depth(): Modified: pypy/dist/pypy/translator/stackless/test/test_yield_current_frame_to_caller.py ============================================================================== --- pypy/dist/pypy/translator/stackless/test/test_yield_current_frame_to_caller.py (original) +++ pypy/dist/pypy/translator/stackless/test/test_yield_current_frame_to_caller.py Mon May 8 19:34:44 2006 @@ -17,9 +17,11 @@ def test_simple(self): def f(): c = g() + assert c return 1 def g(): - self.yield_current_frame_to_caller() + d = self.yield_current_frame_to_caller() + return d data = llinterp_stackless_function(f) assert data == 1 From ericvrp at codespeak.net Mon May 8 21:35:36 2006 From: ericvrp at codespeak.net (ericvrp at codespeak.net) Date: Mon, 8 May 2006 21:35:36 +0200 (CEST) Subject: [pypy-svn] r26979 - pypy/dist/pypy/translator/llvm/test Message-ID: <20060508193536.2FF2C1006E@code0.codespeak.net> Author: ericvrp Date: Mon May 8 21:35:35 2006 New Revision: 26979 Modified: pypy/dist/pypy/translator/llvm/test/test_lladdresses.py Log: Disable llvm test because AddressLinkedList is no longer found Modified: pypy/dist/pypy/translator/llvm/test/test_lladdresses.py ============================================================================== --- pypy/dist/pypy/translator/llvm/test/test_lladdresses.py (original) +++ pypy/dist/pypy/translator/llvm/test/test_lladdresses.py Mon May 8 21:35:35 2006 @@ -117,6 +117,7 @@ assert fn(1) == 2 def test_flavored_malloc2_raw(): + py.test.skip("AddressLinkedList not found") from pypy.rpython.memory.support import AddressLinkedList def f(): From arigo at codespeak.net Mon May 8 22:04:32 2006 From: arigo at codespeak.net (arigo at codespeak.net) Date: Mon, 8 May 2006 22:04:32 +0200 (CEST) Subject: [pypy-svn] r26980 - in pypy/dist/pypy: module/stackless/test translator translator/backendopt translator/c translator/c/test translator/goal translator/stackless translator/stackless/test Message-ID: <20060508200432.A23491006E@code0.codespeak.net> Author: arigo Date: Mon May 8 22:04:28 2006 New Revision: 26980 Removed: pypy/dist/pypy/translator/backendopt/stackless.py Modified: pypy/dist/pypy/module/stackless/test/test_interp_coroutine.py pypy/dist/pypy/translator/c/database.py pypy/dist/pypy/translator/c/funcgen.py pypy/dist/pypy/translator/c/genc.py pypy/dist/pypy/translator/c/node.py pypy/dist/pypy/translator/c/test/test_stackless.py pypy/dist/pypy/translator/c/test/test_tasklets.py pypy/dist/pypy/translator/goal/targetrecursivestandalone.py pypy/dist/pypy/translator/goal/translate.py pypy/dist/pypy/translator/stackless/test/test_depth.py pypy/dist/pypy/translator/stackless/test/test_transform.py pypy/dist/pypy/translator/stackless/test/test_yield_current_frame_to_caller.py pypy/dist/pypy/translator/stackless/transform.py pypy/dist/pypy/translator/translator.py Log: (pedronis, arigo) More push and pull all over the place. Acheived here, is some integration between the stackless transform and GenC. The --stackless option of translate.py means the stackless transform now; the --old-stackless option is available for the old GenC-based stackless.py. Modified: pypy/dist/pypy/module/stackless/test/test_interp_coroutine.py ============================================================================== --- pypy/dist/pypy/module/stackless/test/test_interp_coroutine.py (original) +++ pypy/dist/pypy/module/stackless/test/test_interp_coroutine.py Mon May 8 22:04:28 2006 @@ -4,284 +4,265 @@ import os from pypy.module.stackless.interp_coroutine import costate, Coroutine, AbstractThunk - -costate.__init__() - -def wrap_stackless_function(fn): - from pypy.translator.translator import TranslationContext - from pypy.translator.c.genc import CStandaloneBuilder - from pypy.annotation.model import SomeList, SomeString - from pypy.annotation.listdef import ListDef - from pypy.translator.backendopt.all import backend_optimizations - - def entry_point(argv): - os.write(1, str(fn())) - return 0 - - s_list_of_strings = SomeList(ListDef(None, SomeString())) - s_list_of_strings.listdef.resize() - t = TranslationContext() - t.buildannotator().build_types(entry_point, [s_list_of_strings]) - #t.view() - t.buildrtyper().specialize() - backend_optimizations(t) - cbuilder = CStandaloneBuilder(t, entry_point) - cbuilder.stackless = True - cbuilder.generate_source() - cbuilder.compile() - return cbuilder.cmdexec('') - +from pypy.translator.c.test.test_stackless import StacklessTest +from pypy.translator.c import gc def output(stuff): os.write(2, stuff + '\n') -def test_coroutine(): - - def g(lst, coros): - coro_f, coro_g, coro_h = coros - lst.append(2) - output('g appended 2') - coro_h.switch() - lst.append(5) - output('g appended 5') - - def h(lst, coros): - coro_f, coro_g, coro_h = coros - lst.append(3) - output('h appended 3') - coro_f.switch() - lst.append(7) - output('h appended 7') - - class T(AbstractThunk): - def __init__(self, func, arg1, arg2): - self.func = func - self.arg1 = arg1 - self.arg2 = arg2 - def call(self): - self.func(self.arg1, self.arg2) - - def f(): - lst = [1] - coro_f = costate.main - coro_g = Coroutine() - coro_h = Coroutine() - coros = [coro_f, coro_g, coro_h] - thunk_g = T(g, lst, coros) - output('binding g after f set 1') - coro_g.bind(thunk_g) - thunk_h = T(h, lst, coros) - output('binding h after f set 1') - coro_h.bind(thunk_h) - output('switching to g') - coro_g.switch() - lst.append(4) - output('f appended 4') - coro_g.switch() - lst.append(6) - output('f appended 6') - coro_h.switch() - lst.append(8) - output('f appended 8') - n = 0 - for i in lst: - n = n*10 + i - return n - - data = wrap_stackless_function(f) - assert int(data.strip()) == 12345678 - -def test_coroutine2(): - - class TBase(AbstractThunk): - def call(self): - pass - - class T(TBase): - def __init__(self, func, arg1, arg2): - self.func = func - self.arg1 = arg1 - self.arg2 = arg2 - def call(self): - self.res = self.func(self.arg1, self.arg2) - - class T1(TBase): - def __init__(self, func, arg1): - self.func = func - self.arg1 = arg1 - def call(self): - self.res = self.func(self.arg1) - - def g(lst, coros): - coro_f1, coro_g, coro_h = coros - lst.append(2) - output('g appended 2') - coro_h.switch() - lst.append(5) - output('g appended 5') - output('exiting g') - - def h(lst, coros): - coro_f1, coro_g, coro_h = coros - lst.append(3) - output('h appended 3') - coro_f1.switch() - lst.append(7) - output('h appended 7') - output('exiting h') - - def f1(coro_f1): - lst = [1] - coro_g = Coroutine() - coro_h = Coroutine() - coros = [coro_f1, coro_g, coro_h] - thunk_g = T(g, lst, coros) - output('binding g after f1 set 1') - coro_g.bind(thunk_g) - thunk_h = T(h, lst, coros) - output('binding h after f1 set 1') - coro_h.bind(thunk_h) - output('switching to g') - coro_g.switch() - lst.append(4) - output('f1 appended 4') - coro_g.switch() - lst.append(6) - output('f1 appended 6') - coro_h.switch() - lst.append(8) - output('f1 appended 8') - n = 0 - for i in lst: - n = n*10 + i - output('exiting f1') - return n - - def f(): - coro_f = costate.main - coro_f1 = Coroutine() - thunk_f1 = T1(f1, coro_f1) - output('binding f1 after f set 1') - coro_f1.bind(thunk_f1) - coro_f1.switch() - output('return to main :-(') - return thunk_f1.res - - data = wrap_stackless_function(f) - assert int(data.strip()) == 12345678 - -def test_kill_raise_del_coro(): - class T(AbstractThunk): - def __init__(self, func, arg): - self.func = func - self.arg = arg - def call(self): - self.func(self.arg, self) - - def g(nrec, t, count=0): - t.count = count - if nrec < 0: - raise ValueError - if nrec: - g(nrec-1, t, count+1) - costate.main.switch() - - def f(): - coro_g = Coroutine() - thunk_g = T(g, 42) - coro_g.bind(thunk_g) - coro_g.switch() - res = thunk_g.count - res *= 10 - res |= coro_g.frame is not None - # testing kill - coro_g.kill() - res *= 10 - res |= coro_g.frame is None - coro_g = Coroutine() - thunk_g = T(g, -42) - coro_g.bind(thunk_g) - try: + +class TestCoroutine(StacklessTest): + backendopt = True + stacklessmode = True + gcpolicy = gc.BoehmGcPolicy + + def setup_meth(self): + costate.__init__() + + def test_coroutine(self): + + def g(lst, coros): + coro_f, coro_g, coro_h = coros + lst.append(2) + output('g appended 2') + coro_h.switch() + lst.append(5) + output('g appended 5') + + def h(lst, coros): + coro_f, coro_g, coro_h = coros + lst.append(3) + output('h appended 3') + coro_f.switch() + lst.append(7) + output('h appended 7') + + class T(AbstractThunk): + def __init__(self, func, arg1, arg2): + self.func = func + self.arg1 = arg1 + self.arg2 = arg2 + def call(self): + self.func(self.arg1, self.arg2) + + def f(): + lst = [1] + coro_f = costate.main + coro_g = Coroutine() + coro_h = Coroutine() + coros = [coro_f, coro_g, coro_h] + thunk_g = T(g, lst, coros) + output('binding g after f set 1') + coro_g.bind(thunk_g) + thunk_h = T(h, lst, coros) + output('binding h after f set 1') + coro_h.bind(thunk_h) + output('switching to g') coro_g.switch() - except ValueError: - res += 500 - return res - - data = wrap_stackless_function(f) - assert int(data.strip()) == 4711 - -def test_tree_compare(): - class Node: - def __init__(self, value, left=None, right=None): - self.value = value - self.left = left - self.right = right - def __repr__(self): - return 'Node(%r, %r, %r)'%(self.value, self.left, self.right) - - tree1 = Node(1, Node(2, Node(3))) - tree2 = Node(1, Node(3, Node(2))) - tree3 = Node(1, Node(2), Node(3)) - - class Producer(AbstractThunk): - def __init__(self, tree, objects, consumer): - self.tree = tree - self.objects = objects - self.consumer = consumer - def produce(self, t): - if t is None: - return - self.objects.append(t.value) - self.consumer.switch() - self.produce(t.left) - self.produce(t.right) - def call(self): - self.produce(self.tree) - while 1: - self.consumer.switch() - class Consumer(AbstractThunk): - def __init__(self, tree, objects, producer): - self.tree = tree - self.objects = objects - self.producer = producer - def consume(self, t): - if t is None: - return True - self.producer.switch() - if not self.objects: - return False - if self.objects.pop(0) != t.value: - return False - if not self.consume(t.left): - return False - return self.consume(t.right) - - def call(self): - self.result = self.consume(self.tree) + lst.append(4) + output('f appended 4') + coro_g.switch() + lst.append(6) + output('f appended 6') + coro_h.switch() + lst.append(8) + output('f appended 8') + n = 0 + for i in lst: + n = n*10 + i + return n + + data = self.wrap_stackless_function(f) + assert data == 12345678 + + def test_coroutine2(self): + + class TBase(AbstractThunk): + def call(self): + pass + + class T(TBase): + def __init__(self, func, arg1, arg2): + self.func = func + self.arg1 = arg1 + self.arg2 = arg2 + def call(self): + self.res = self.func(self.arg1, self.arg2) + + class T1(TBase): + def __init__(self, func, arg1): + self.func = func + self.arg1 = arg1 + def call(self): + self.res = self.func(self.arg1) + + def g(lst, coros): + coro_f1, coro_g, coro_h = coros + lst.append(2) + output('g appended 2') + coro_h.switch() + lst.append(5) + output('g appended 5') + output('exiting g') + + def h(lst, coros): + coro_f1, coro_g, coro_h = coros + lst.append(3) + output('h appended 3') + coro_f1.switch() + lst.append(7) + output('h appended 7') + output('exiting h') + + def f1(coro_f1): + lst = [1] + coro_g = Coroutine() + coro_h = Coroutine() + coros = [coro_f1, coro_g, coro_h] + thunk_g = T(g, lst, coros) + output('binding g after f1 set 1') + coro_g.bind(thunk_g) + thunk_h = T(h, lst, coros) + output('binding h after f1 set 1') + coro_h.bind(thunk_h) + output('switching to g') + coro_g.switch() + lst.append(4) + output('f1 appended 4') + coro_g.switch() + lst.append(6) + output('f1 appended 6') + coro_h.switch() + lst.append(8) + output('f1 appended 8') + n = 0 + for i in lst: + n = n*10 + i + output('exiting f1') + return n + + def f(): + coro_f = costate.main + coro_f1 = Coroutine() + thunk_f1 = T1(f1, coro_f1) + output('binding f1 after f set 1') + coro_f1.bind(thunk_f1) + coro_f1.switch() + output('return to main :-(') + return thunk_f1.res + + data = self.wrap_stackless_function(f) + assert data == 12345678 + + def test_kill_raise_del_coro(self): + class T(AbstractThunk): + def __init__(self, func, arg): + self.func = func + self.arg = arg + def call(self): + self.func(self.arg, self) + + def g(nrec, t, count=0): + t.count = count + if nrec < 0: + raise ValueError + if nrec: + g(nrec-1, t, count+1) costate.main.switch() - def pre_order_eq(t1, t2): - objects = [] - producer = Coroutine() - consumer = Coroutine() - - producer.bind(Producer(t1, objects, consumer)) - cons = Consumer(t2, objects, producer) - consumer.bind(cons) - - consumer.switch() - - return cons.result - - def ep(): - return "%d %d %d %d"%(pre_order_eq(tree1, tree2), - pre_order_eq(tree1, tree1), - pre_order_eq(tree1, tree3), - pre_order_eq(tree2, tree1), - - ) - - output = wrap_stackless_function(ep) - assert output.strip() == '0 1 1 0' - - + def f(): + coro_g = Coroutine() + thunk_g = T(g, 42) + coro_g.bind(thunk_g) + coro_g.switch() + res = thunk_g.count + res *= 10 + res |= coro_g.frame is not None + # testing kill + coro_g.kill() + res *= 10 + res |= coro_g.frame is None + coro_g = Coroutine() + thunk_g = T(g, -42) + coro_g.bind(thunk_g) + try: + coro_g.switch() + except ValueError: + res += 500 + return res + + data = self.wrap_stackless_function(f) + assert data == 4711 + + def test_tree_compare(self): + class Node: + def __init__(self, value, left=None, right=None): + self.value = value + self.left = left + self.right = right + def __repr__(self): + return 'Node(%r, %r, %r)'%(self.value, self.left, self.right) + + tree1 = Node(1, Node(2, Node(3))) + tree2 = Node(1, Node(3, Node(2))) + tree3 = Node(1, Node(2), Node(3)) + + class Producer(AbstractThunk): + def __init__(self, tree, objects, consumer): + self.tree = tree + self.objects = objects + self.consumer = consumer + def produce(self, t): + if t is None: + return + self.objects.append(t.value) + self.consumer.switch() + self.produce(t.left) + self.produce(t.right) + def call(self): + self.produce(self.tree) + while 1: + self.consumer.switch() + class Consumer(AbstractThunk): + def __init__(self, tree, objects, producer): + self.tree = tree + self.objects = objects + self.producer = producer + def consume(self, t): + if t is None: + return True + self.producer.switch() + if not self.objects: + return False + if self.objects.pop(0) != t.value: + return False + if not self.consume(t.left): + return False + return self.consume(t.right) + + def call(self): + self.result = self.consume(self.tree) + costate.main.switch() + + def pre_order_eq(t1, t2): + objects = [] + producer = Coroutine() + consumer = Coroutine() + + producer.bind(Producer(t1, objects, consumer)) + cons = Consumer(t2, objects, producer) + consumer.bind(cons) + + consumer.switch() + + return cons.result + + def ep(): + return int("%d%d%d%d"%(pre_order_eq(tree1, tree2), + pre_order_eq(tree1, tree1), + pre_order_eq(tree1, tree3), + pre_order_eq(tree2, tree1), + )) + + output = self.wrap_stackless_function(ep) + assert output == int('0110') Modified: pypy/dist/pypy/translator/c/database.py ============================================================================== --- pypy/dist/pypy/translator/c/database.py (original) +++ pypy/dist/pypy/translator/c/database.py Mon May 8 22:04:28 2006 @@ -21,6 +21,7 @@ # ____________________________________________________________ class LowLevelDatabase(object): + stacklesstransformer = None def __init__(self, translator=None, standalone=False, gcpolicy=None, thread_enabled=False): self.translator = translator Modified: pypy/dist/pypy/translator/c/funcgen.py ============================================================================== --- pypy/dist/pypy/translator/c/funcgen.py (original) +++ pypy/dist/pypy/translator/c/funcgen.py Mon May 8 22:04:28 2006 @@ -33,12 +33,16 @@ blocknum oldgraph""".split() - def __init__(self, graph, db, cpython_exc=False, functionname=None): + def __init__(self, graph, db, cpython_exc=False, functionname=None, + do_stackless=True): self.graph = graph self.db = db self.gcpolicy = db.gcpolicy self.cpython_exc = cpython_exc self.functionname = functionname + # apply the stackless transformation + if db.stacklesstransformer and do_stackless: + db.stacklesstransformer.transform_graph(graph) # apply the exception transformation if self.db.exctransformer: self.db.exctransformer.create_exception_handling(self.graph) Modified: pypy/dist/pypy/translator/c/genc.py ============================================================================== --- pypy/dist/pypy/translator/c/genc.py (original) +++ pypy/dist/pypy/translator/c/genc.py Mon May 8 22:04:28 2006 @@ -20,12 +20,12 @@ _compiled = False symboltable = None stackless = False - use_stackless_transformation = False modulename = None def __init__(self, translator, entrypoint, gcpolicy=None, libraries=None, thread_enabled=False): self.translator = translator self.entrypoint = entrypoint + self.originalentrypoint = entrypoint self.gcpolicy = gcpolicy self.thread_enabled = thread_enabled @@ -39,10 +39,19 @@ db = LowLevelDatabase(translator, standalone=self.standalone, gcpolicy=self.gcpolicy, thread_enabled=self.thread_enabled) + assert self.stackless in (False, 'old', True) if self.stackless: - from pypy.translator.c.stackless import StacklessData - db.stacklessdata = StacklessData(db) - db.use_stackless_transformation = self.use_stackless_transformation + if not self.standalone: + raise Exception("stackless: only for stand-alone builds") + if self.stackless == 'old': + from pypy.translator.c.stackless import StacklessData + db.stacklessdata = StacklessData(db) + else: + from pypy.translator.stackless.transform import \ + StacklessTransformer + db.stacklesstransformer = StacklessTransformer(translator, + self.originalentrypoint) + self.entrypoint = db.stacklesstransformer.slp_entry_point # pass extra options into pyobjmaker if pyobj_options: @@ -107,12 +116,9 @@ else: if CBuilder.have___thread: defines['HAVE___THREAD'] = 1 - if self.stackless: + if self.stackless == 'old': defines['USE_STACKLESS'] = '1' defines['USE_OPTIMIZED_STACKLESS_UNWIND'] = '1' - if self.use_stackless_transformation: #set in test_stackless.py - from pypy.translator.backendopt.stackless import stackless - stackless(translator, db.stacklessdata) cfile, extra = gen_source_standalone(db, modulename, targetdir, entrypointname = pfname, defines = defines) @@ -573,7 +579,7 @@ sg.set_strategy(targetdir) sg.gen_readable_parts_of_source(f) - # 2bis) stackless data + # 2bis) old-style stackless data if hasattr(database, 'stacklessdata'): database.stacklessdata.writefiles(sg) Modified: pypy/dist/pypy/translator/c/node.py ============================================================================== --- pypy/dist/pypy/translator/c/node.py (original) +++ pypy/dist/pypy/translator/c/node.py Mon May 8 22:04:28 2006 @@ -644,7 +644,7 @@ fnobj._callable,) elif hasattr(fnobj, 'graph'): cpython_exc = getattr(fnobj, 'exception_policy', None) == "CPython" - if hasattr(db, 'stacklessdata') and not db.use_stackless_transformation: + if hasattr(db, 'stacklessdata'): split_slp_function = False if split_slp_function: from pypy.translator.c.stackless import SlpSaveOnlyFunctionCodeGenerator, \ @@ -655,10 +655,8 @@ from pypy.translator.c.stackless import SlpFunctionCodeGenerator return [SlpFunctionCodeGenerator(fnobj.graph, db, cpython_exc, functionname)] else: - if db.translator and db.translator.stacklesstransformer is not None: - if not hasattr(fnobj, 'isgchelper'): - db.translator.stacklesstransformer.transform_graph(fnobj.graph) - return [FunctionCodeGenerator(fnobj.graph, db, cpython_exc, functionname)] + return [FunctionCodeGenerator(fnobj.graph, db, cpython_exc, functionname, + do_stackless = not getattr(fnobj, 'isgchelper', False))] elif getattr(fnobj, 'external', None) == 'C': # deprecated case if hasattr(fnobj, 'includes'): Modified: pypy/dist/pypy/translator/c/test/test_stackless.py ============================================================================== --- pypy/dist/pypy/translator/c/test/test_stackless.py (original) +++ pypy/dist/pypy/translator/c/test/test_stackless.py Mon May 8 22:04:28 2006 @@ -11,6 +11,7 @@ class StacklessTest(object): backendopt = False + stacklessmode = 'old' def setup_class(cls): import py @@ -43,8 +44,7 @@ insert_ll_stackcheck(t) cbuilder = CStandaloneBuilder(t, entry_point, gcpolicy=self.gcpolicy) - cbuilder.stackless = True - #cbuilder.use_stackless_transformation = True + cbuilder.stackless = self.stacklessmode cbuilder.generate_source() cbuilder.compile() res = cbuilder.cmdexec('') @@ -306,9 +306,4 @@ # ____________________________________________________________ class TestStacklessTransformBoehm(TestStacklessBoehm): - - def wrap_stackless_function(self, fn): - # temporary way of doing this - #import py; py.test.skip("in-progress") - from pypy.translator.stackless.test import test_transform - return test_transform.run_stackless_function(fn) + stacklessmode = True Modified: pypy/dist/pypy/translator/c/test/test_tasklets.py ============================================================================== --- pypy/dist/pypy/translator/c/test/test_tasklets.py (original) +++ pypy/dist/pypy/translator/c/test/test_tasklets.py Mon May 8 22:04:28 2006 @@ -500,9 +500,4 @@ # ____________________________________________________________ class TestTaskletsStacklessTransform(TestTasklets): - - def wrap_stackless_function(self, fn): - # temporary way of doing this - #import py; py.test.skip("in-progress") - from pypy.translator.stackless.test import test_transform - return test_transform.run_stackless_function(fn) + stacklessmode = True Modified: pypy/dist/pypy/translator/goal/targetrecursivestandalone.py ============================================================================== --- pypy/dist/pypy/translator/goal/targetrecursivestandalone.py (original) +++ pypy/dist/pypy/translator/goal/targetrecursivestandalone.py Mon May 8 22:04:28 2006 @@ -22,7 +22,7 @@ return ackermann(x - 1, ackermann(x, y - 1)) def entry_point(argv): - debug(str(ackermann(3, 27)) + "\n") + debug(str(ackermann(3, 12)) + "\n") return 0 # _____ Define and setup target ___ Modified: pypy/dist/pypy/translator/goal/translate.py ============================================================================== --- pypy/dist/pypy/translator/goal/translate.py (original) +++ pypy/dist/pypy/translator/goal/translate.py Mon May 8 22:04:28 2006 @@ -50,7 +50,8 @@ '2_gc': [OPT(('--gc',), "Garbage collector", ['boehm', 'ref', 'framework', 'none', 'exact_boehm'])], '3_stackless': [OPT(('--stackless',), "Stackless code generation", True)], - '4_merge_if_blocks': [OPT(('--no-if-blocks-merge',), "Do not merge if ... elif ... chains and use a switch statement for them.", False)], + '4_stackless': [OPT(('--old-stackless',), "Stackless code generation (old GenC way)", 'old')], + '5_merge_if_blocks': [OPT(('--no-if-blocks-merge',), "Do not merge if ... elif ... chains and use a switch statement for them.", False)], }, @@ -192,6 +193,9 @@ opt_setup['type'] = 'int' elif choice is str: opt_setup['type'] = 'string' + else: + opt_setup['action'] = 'store_const' + opt_setup['const'] = choice grp.add_option(*names, **opt_setup) Modified: pypy/dist/pypy/translator/stackless/test/test_depth.py ============================================================================== --- pypy/dist/pypy/translator/stackless/test/test_depth.py (original) +++ pypy/dist/pypy/translator/stackless/test/test_depth.py Mon May 8 22:04:28 2006 @@ -1,100 +1,89 @@ from pypy.translator.stackless.test.test_transform import \ llinterp_stackless_function, run_stackless_function -from pypy.translator.stackless import code from pypy.rpython import rstack import py import os -class TestFromCode: - stack_frames_depth = staticmethod(code.stack_frames_depth) +def test_simple(): + def g1(): + "just to check Void special cases around the code" + def g2(ignored): + pass + g1() + def f(n): + g1() + if n > 0: + res = f(n-1) + else: + res = rstack.stack_frames_depth() + g2(g1) + return res + + def fn(): + count0 = f(0) + count10 = f(10) + return count10 - count0 + + res = llinterp_stackless_function(fn) + assert res == 10 + + res = run_stackless_function(fn) + assert res == 10 + +def test_with_ptr(): + def f(n): + if n > 0: + res = f(n-1) + else: + res = rstack.stack_frames_depth(), 1 + return res + + def fn(): + count0, _ = f(0) + count10, _ = f(10) + return count10 - count0 + + res = llinterp_stackless_function(fn) + assert res == 10 + + res = run_stackless_function(fn) + assert res == 10 + +def test_manytimes(): + def f(n): + if n > 0: + res = f(n-1) + else: + res = rstack.stack_frames_depth(), 1 + return res + + def fn(): + count0, _ = f(0) + count10, _ = f(100) + return count10 - count0 + + res = llinterp_stackless_function(fn) + assert res == 100 + + res = run_stackless_function(fn) + assert res == 100 + +def test_arguments(): + def f(n, d, t): + if n > 0: + res = f(n-1, d, t) + else: + res = rstack.stack_frames_depth(), d, t + return res + + def fn(): + count0, d, t = f(0, 5.5, (1, 2)) + count10, d, t = f(10, 5.5, (1, 2)) + return count10 - count0 + int(d) - def _freeze_(self): - return True + res = llinterp_stackless_function(fn) + assert res == 15 - def test_simple(self): - def g1(): - "just to check Void special cases around the code" - def g2(ignored): - pass - g1() - def f(n): - g1() - if n > 0: - res = f(n-1) - else: - res = self.stack_frames_depth() - g2(g1) - return res - - def fn(): - count0 = f(0) - count10 = f(10) - return count10 - count0 - - res = llinterp_stackless_function(fn) - assert res == 10 - - res = run_stackless_function(fn) - assert res == 10 - - def test_with_ptr(self): - def f(n): - if n > 0: - res = f(n-1) - else: - res = self.stack_frames_depth(), 1 - return res - - def fn(): - count0, _ = f(0) - count10, _ = f(10) - return count10 - count0 - - res = llinterp_stackless_function(fn) - assert res == 10 - - res = run_stackless_function(fn) - assert res == 10 - - def test_manytimes(self): - def f(n): - if n > 0: - res = f(n-1) - else: - res = self.stack_frames_depth(), 1 - return res - - def fn(): - count0, _ = f(0) - count10, _ = f(100) - return count10 - count0 - - res = llinterp_stackless_function(fn) - assert res == 100 - - res = run_stackless_function(fn) - assert res == 100 - - def test_arguments(self): - def f(n, d, t): - if n > 0: - res = f(n-1, d, t) - else: - res = self.stack_frames_depth(), d, t - return res - - def fn(): - count0, d, t = f(0, 5.5, (1, 2)) - count10, d, t = f(10, 5.5, (1, 2)) - return count10 - count0 + int(d) - - res = llinterp_stackless_function(fn) - assert res == 15 - - res = run_stackless_function(fn) - assert res == 15 - - -class TestFromRStack(TestFromCode): - stack_frames_depth = staticmethod(rstack.stack_frames_depth) + res = run_stackless_function(fn) + assert res == 15 Modified: pypy/dist/pypy/translator/stackless/test/test_transform.py ============================================================================== --- pypy/dist/pypy/translator/stackless/test/test_transform.py (original) +++ pypy/dist/pypy/translator/stackless/test/test_transform.py Mon May 8 22:04:28 2006 @@ -165,17 +165,6 @@ t = TranslationContext() annotator = t.buildannotator() annotator.policy.allow_someobjects = False - bk = annotator.bookkeeper - # we want to make sure that the annotator knows what - # code.UnwindException looks like very early on, because otherwise - # it can get mutated during the annotation of the low level - # helpers which can cause slp_main_loop to get re-annotated after - # it is rtyped. which is bad. - unwind_def = bk.getuniqueclassdef(code.UnwindException) - unwind_def.generalize_attr('frame_bottom', - annmodel.SomePtr(lltype.Ptr(code.STATE_HEADER))) - attrdef = unwind_def.attrs['frame_bottom'] - attrdef.readonly = False s_returnvar = annotator.build_types(fn, [s_list_of_strings]) if not isinstance(s_returnvar, annmodel.SomeInteger): @@ -191,20 +180,14 @@ def run_stackless_function(fn): def entry_point(argv): - try: - r = fn() - except code.UnwindException, u: - code.slp_main_loop() - r = code.global_state.retval_long + r = fn() os.write(1, str(r)+'\n') return 0 - entry_point.stackless_explicit = True t = rtype_stackless_function(entry_point) - t.stacklesstransformer = StacklessTransformer(t) - cbuilder = CStandaloneBuilder(t, entry_point, gcpolicy=gc.BoehmGcPolicy) + cbuilder.stackless = True cbuilder.generate_source() if conftest.option.view: t.view() @@ -213,24 +196,18 @@ return int(res.strip()) def llinterp_stackless_function(fn): - def entry_point(argv): - try: - r = fn() - except code.UnwindException, u: - code.slp_main_loop() - return code.global_state.retval_long - return r - entry_point.stackless_explicit = True - - t = rtype_stackless_function(entry_point) - st = StacklessTransformer(t) + def wrapper(argv): + return fn() + t = rtype_stackless_function(wrapper) + st = StacklessTransformer(t, wrapper) st.transform_all() if conftest.option.view: t.view() + graph = graphof(t, st.slp_entry_point) r_list_of_strings = t.rtyper.getrepr( - t.annotator.binding(graphof(t, entry_point).startblock.inputargs[0])) + t.annotator.binding(graph.startblock.inputargs[0])) ll_list = r_list_of_strings.convert_const(['']) interp = llinterp.LLInterpreter(t.rtyper) - res = interp.eval_graph(graphof(t, entry_point), [ll_list]) + res = interp.eval_graph(graph, [ll_list]) return res Modified: pypy/dist/pypy/translator/stackless/test/test_yield_current_frame_to_caller.py ============================================================================== --- pypy/dist/pypy/translator/stackless/test/test_yield_current_frame_to_caller.py (original) +++ pypy/dist/pypy/translator/stackless/test/test_yield_current_frame_to_caller.py Mon May 8 22:04:28 2006 @@ -1,84 +1,66 @@ from pypy.translator.stackless.test.test_transform import \ llinterp_stackless_function, run_stackless_function -from pypy.translator.stackless import code from pypy.rpython import rstack import py import os -class TestFromCode: - yield_current_frame_to_caller = staticmethod( - code.yield_current_frame_to_caller) - switch = staticmethod(code.ll_frame_switch) - - def _freeze_(self): - return True - - def test_simple(self): - def f(): - c = g() - assert c - return 1 - def g(): - d = self.yield_current_frame_to_caller() - return d - - data = llinterp_stackless_function(f) - assert data == 1 - - res = run_stackless_function(f) - assert res == 1 - - def test_switch(self): - def f(): - c = g() - self.switch(c) - return 1 - def g(): - d = self.yield_current_frame_to_caller() - return d - - data = llinterp_stackless_function(f) - assert data == 1 - - res = run_stackless_function(f) - assert res == 1 - - def test_yield_frame(self): - - def g(lst): - lst.append(2) - frametop_before_5 = self.yield_current_frame_to_caller() - lst.append(4) - frametop_before_7 = self.switch(frametop_before_5) - lst.append(6) - return frametop_before_7 - - def f(): - lst = [1] - frametop_before_4 = g(lst) - lst.append(3) - frametop_before_6 = self.switch(frametop_before_4) - lst.append(5) - frametop_after_return = self.switch(frametop_before_6) - lst.append(7) - assert not frametop_after_return - n = 0 - for i in lst: - n = n*10 + i - return n - - data = llinterp_stackless_function(f) - assert data == 1234567 - - res = run_stackless_function(f) - assert res == 1234567 - - -class TestFromRStack(TestFromCode): - yield_current_frame_to_caller = staticmethod( - rstack.yield_current_frame_to_caller) - - def switch(state): - return state.switch() - switch = staticmethod(switch) +def test_simple(): + def f(): + c = g() + assert c + return 1 + def g(): + d = rstack.yield_current_frame_to_caller() + return d + + data = llinterp_stackless_function(f) + assert data == 1 + + res = run_stackless_function(f) + assert res == 1 + +def test_switch(): + def f(): + c = g() + c.switch() + return 1 + def g(): + d = rstack.yield_current_frame_to_caller() + return d + + data = llinterp_stackless_function(f) + assert data == 1 + + res = run_stackless_function(f) + assert res == 1 + +def test_yield_frame(): + + def g(lst): + lst.append(2) + frametop_before_5 = rstack.yield_current_frame_to_caller() + lst.append(4) + frametop_before_7 = frametop_before_5.switch() + lst.append(6) + return frametop_before_7 + + def f(): + lst = [1] + frametop_before_4 = g(lst) + lst.append(3) + frametop_before_6 = frametop_before_4.switch() + lst.append(5) + frametop_after_return = frametop_before_6.switch() + lst.append(7) + assert not frametop_after_return + n = 0 + for i in lst: + n = n*10 + i + return n + + data = llinterp_stackless_function(f) + assert data == 1234567 + + res = run_stackless_function(f) + assert res == 1234567 Modified: pypy/dist/pypy/translator/stackless/transform.py ============================================================================== --- pypy/dist/pypy/translator/stackless/transform.py (original) +++ pypy/dist/pypy/translator/stackless/transform.py Mon May 8 22:04:28 2006 @@ -31,7 +31,7 @@ elif T in [lltype.SignedLongLong, lltype.UnsignedLongLong]: return lltype.SignedLongLong elif T is llmemory.Address: - return lltype.Address + return llmemory.Address elif isinstance(T, lltype.Primitive): return lltype.Signed else: @@ -80,7 +80,7 @@ self.fieldnames = fieldnames class StacklessTransformer(object): - def __init__(self, translator): + def __init__(self, translator, entrypoint): self.translator = translator edata = translator.rtyper.getexceptiondata() @@ -95,6 +95,21 @@ mixlevelannotator = MixLevelHelperAnnotator(translator.rtyper) l2a = annmodel.lltype_to_annotation + def slp_entry_point(argv): + try: + r = entrypoint(argv) + except code.UnwindException, u: + code.slp_main_loop() + return code.global_state.retval_long + return r + slp_entry_point.stackless_explicit = True + + self.slp_entry_point = slp_entry_point + oldgraph = bk.getdesc(entrypoint).cachedgraph(None) + s_argv = translator.annotator.binding(oldgraph.getargs()[0]) + self.slp_entry_point_ptr = mixlevelannotator.constfunc( + slp_entry_point, [s_argv], annmodel.SomeInteger()) + unwinddef = bk.getuniqueclassdef(code.UnwindException) self.add_frame_state_ptr = mixlevelannotator.constfunc( code.add_frame_state, Modified: pypy/dist/pypy/translator/translator.py ============================================================================== --- pypy/dist/pypy/translator/translator.py (original) +++ pypy/dist/pypy/translator/translator.py Mon May 8 22:04:28 2006 @@ -30,7 +30,6 @@ raise TypeError("unexpected keyword argument") self.annotator = None self.rtyper = None - self.stacklesstransformer = None self.graphs = [] # [graph] self.callgraph = {} # {opaque_tag: (caller-graph, callee-graph)} self._prebuilt_graphs = {} # only used by the pygame viewer From arigo at codespeak.net Mon May 8 22:35:08 2006 From: arigo at codespeak.net (arigo at codespeak.net) Date: Mon, 8 May 2006 22:35:08 +0200 (CEST) Subject: [pypy-svn] r26981 - pypy/dist/pypy/translator/stackless Message-ID: <20060508203508.2711A1006E@code0.codespeak.net> Author: arigo Date: Mon May 8 22:35:07 2006 New Revision: 26981 Modified: pypy/dist/pypy/translator/stackless/transform.py Log: (pedronis, arigo) Avoid copying unnecessarily annotations. Modified: pypy/dist/pypy/translator/stackless/transform.py ============================================================================== --- pypy/dist/pypy/translator/stackless/transform.py (original) +++ pypy/dist/pypy/translator/stackless/transform.py Mon May 8 22:35:07 2006 @@ -282,7 +282,7 @@ return varmap[arg] else: assert arg in [l.last_exception, l.last_exc_value] - r = unsimplify.copyvar(self.translator, arg) + r = unsimplify.copyvar(None, arg) varmap[arg] = r return r else: @@ -302,7 +302,7 @@ resume_point.var_result.concretetype, retval) convertblock = unsimplify.insert_empty_block( - self.translator, newblock.exits[0], llops) + None, newblock.exits[0], llops) # begin ouch! for index, linkvar in enumerate(convertblock.exits[0].args): # does this var come from retval ? @@ -425,9 +425,9 @@ edata = rtyper.getexceptiondata() etype = edata.lltype_of_exception_type evalue = edata.lltype_of_exception_value - inputargs = [unsimplify.copyvar(self.translator, v) for v in varstosave] + inputargs = [unsimplify.copyvar(None, v) for v in varstosave] var_unwind_exception = unsimplify.copyvar( - self.translator, var_unwind_exception) + None, var_unwind_exception) frame_type, fieldnames = self.frame_type_for_vars(varstosave) From arigo at codespeak.net Mon May 8 23:16:28 2006 From: arigo at codespeak.net (arigo at codespeak.net) Date: Mon, 8 May 2006 23:16:28 +0200 (CEST) Subject: [pypy-svn] r26982 - pypy/dist/pypy/translator/goal Message-ID: <20060508211628.AC7A51006E@code0.codespeak.net> Author: arigo Date: Mon May 8 23:16:27 2006 New Revision: 26982 Modified: pypy/dist/pypy/translator/goal/targetpypystandalone.py Log: Disable "translate.pypy --stackless" unless you remove the 'raise' manually for experimentation. This is to prevent the cron job on snake to try for itself and explode all the RAM and swap. Modified: pypy/dist/pypy/translator/goal/targetpypystandalone.py ============================================================================== --- pypy/dist/pypy/translator/goal/targetpypystandalone.py (original) +++ pypy/dist/pypy/translator/goal/targetpypystandalone.py Mon May 8 23:16:27 2006 @@ -89,6 +89,7 @@ # thread might appear twice now, but the objspace can handle this usemodules.append('thread') if options.stackless: + raise MemoryError("in-progress, but maybe consumes tons of memory") usemodules.append('stackless') space = StdObjSpace(nofaking=True, From arigo at codespeak.net Mon May 8 23:17:06 2006 From: arigo at codespeak.net (arigo at codespeak.net) Date: Mon, 8 May 2006 23:17:06 +0200 (CEST) Subject: [pypy-svn] r26983 - pypy/dist/pypy/rpython Message-ID: <20060508211706.3437A1006E@code0.codespeak.net> Author: arigo Date: Mon May 8 23:17:04 2006 New Revision: 26983 Modified: pypy/dist/pypy/rpython/rlist.py Log: (pedronis, arigo) Bug fix: checking for "a memory pattern of zero" isn't so obvious. Modified: pypy/dist/pypy/rpython/rlist.py ============================================================================== --- pypy/dist/pypy/rpython/rlist.py (original) +++ pypy/dist/pypy/rpython/rlist.py Mon May 8 23:17:04 2006 @@ -3,7 +3,8 @@ from pypy.annotation import model as annmodel from pypy.rpython.rmodel import Repr, IteratorRepr, IntegerRepr, inputconst from pypy.rpython.rslice import AbstractSliceRepr -from pypy.rpython.lltypesystem.lltype import typeOf, Ptr, Void, Signed, Bool, nullptr +from pypy.rpython.lltypesystem.lltype import typeOf, Ptr, Void, Signed, Bool +from pypy.rpython.lltypesystem.lltype import nullptr, Char, UniChar from pypy.rpython import robject def dum_checkidx(): pass @@ -350,7 +351,12 @@ if count < 0: count = 0 l = LIST.ll_newlist(count) - if item: # as long as malloc it is known to zero the allocated memory avoid zeroing twice + T = typeOf(item) + if T is Char or T is UniChar: + check = ord(item) + else: + check = item + if check: # as long as malloc it is known to zero the allocated memory avoid zeroing twice i = 0 while i < count: l.ll_setitem_fast(i, item) From arigo at codespeak.net Tue May 9 00:10:13 2006 From: arigo at codespeak.net (arigo at codespeak.net) Date: Tue, 9 May 2006 00:10:13 +0200 (CEST) Subject: [pypy-svn] r26984 - pypy/dist/pypy/translator/goal Message-ID: <20060508221013.D601A1006F@code0.codespeak.net> Author: arigo Date: Tue May 9 00:10:12 2006 New Revision: 26984 Modified: pypy/dist/pypy/translator/goal/targetpypystandalone.py pypy/dist/pypy/translator/goal/translate.py Log: For now, keep its original meaning to the --stackless option and use --new-stackless for the stackless transformer. Modified: pypy/dist/pypy/translator/goal/targetpypystandalone.py ============================================================================== --- pypy/dist/pypy/translator/goal/targetpypystandalone.py (original) +++ pypy/dist/pypy/translator/goal/targetpypystandalone.py Tue May 9 00:10:12 2006 @@ -89,7 +89,8 @@ # thread might appear twice now, but the objspace can handle this usemodules.append('thread') if options.stackless: - raise MemoryError("in-progress, but maybe consumes tons of memory") + if options.stackless != 'old': + raise MemoryError("in-progress; might consume tons of memory") usemodules.append('stackless') space = StdObjSpace(nofaking=True, Modified: pypy/dist/pypy/translator/goal/translate.py ============================================================================== --- pypy/dist/pypy/translator/goal/translate.py (original) +++ pypy/dist/pypy/translator/goal/translate.py Tue May 9 00:10:12 2006 @@ -49,8 +49,8 @@ '1_backend': [OPT(('-b', '--backend'), "Backend", ['c', 'llvm', 'cl', 'squeak', 'js'])], '2_gc': [OPT(('--gc',), "Garbage collector", ['boehm', 'ref', 'framework', 'none', 'exact_boehm'])], - '3_stackless': [OPT(('--stackless',), "Stackless code generation", True)], - '4_stackless': [OPT(('--old-stackless',), "Stackless code generation (old GenC way)", 'old')], + '3_stackless': [OPT(('--new-stackless',), "Stackless code generation (graph transformer)", True)], + '4_stackless': [OPT(('--stackless',), "Stackless code generation (old GenC way)", 'old')], '5_merge_if_blocks': [OPT(('--no-if-blocks-merge',), "Do not merge if ... elif ... chains and use a switch statement for them.", False)], }, From pedronis at codespeak.net Tue May 9 02:23:37 2006 From: pedronis at codespeak.net (pedronis at codespeak.net) Date: Tue, 9 May 2006 02:23:37 +0200 (CEST) Subject: [pypy-svn] r26987 - in pypy/dist/pypy/translator/stackless: . test Message-ID: <20060509002337.5CF8F1006F@code0.codespeak.net> Author: pedronis Date: Tue May 9 02:23:36 2006 New Revision: 26987 Modified: pypy/dist/pypy/translator/stackless/test/test_transform.py pypy/dist/pypy/translator/stackless/transform.py Log: fix saving of extra values for the exception cases. test. Modified: pypy/dist/pypy/translator/stackless/test/test_transform.py ============================================================================== --- pypy/dist/pypy/translator/stackless/test/test_transform.py (original) +++ pypy/dist/pypy/translator/stackless/test/test_transform.py Tue May 9 02:23:36 2006 @@ -141,7 +141,29 @@ try: y = h(one()) except KeyError: - y = -1 + y = -one() + return y + 1 + res = llinterp_stackless_function(example) + assert res == 0 + +def test_resume_with_exception_handling_with_vals(): + def check(x): + if x: + raise code.UnwindException + def g(x): + check(x) + if x: + raise KeyError + else: + return x + 1 + def h(x): + return g(x) + def example(): + y = one() + try: + y = h(one()) + except KeyError: + y = y - 2 return y + 1 res = llinterp_stackless_function(example) assert res == 0 Modified: pypy/dist/pypy/translator/stackless/transform.py ============================================================================== --- pypy/dist/pypy/translator/stackless/transform.py (original) +++ pypy/dist/pypy/translator/stackless/transform.py Tue May 9 02:23:36 2006 @@ -391,13 +391,14 @@ # value is not again used. args = [] for l in block.exits: - for arg in link.args: + for arg in l.args: if isinstance(arg, model.Variable) \ and arg.concretetype is not lltype.Void \ and arg is not op.result \ - and arg not in args: + and arg not in args \ + and arg not in [l.last_exception, l.last_exc_value]: args.append(arg) - + save_block, frame_state_type, fieldnames = \ self.generate_save_block(args, var_unwind_exception) From arigo at codespeak.net Tue May 9 11:20:43 2006 From: arigo at codespeak.net (arigo at codespeak.net) Date: Tue, 9 May 2006 11:20:43 +0200 (CEST) Subject: [pypy-svn] r26991 - in pypy/dist/pypy/translator/stackless: . test Message-ID: <20060509092043.7A5F110071@code0.codespeak.net> Author: arigo Date: Tue May 9 11:20:42 2006 New Revision: 26991 Modified: pypy/dist/pypy/translator/stackless/test/test_transform.py pypy/dist/pypy/translator/stackless/transform.py Log: Trivial bug, non-trivial test, and fix. Modified: pypy/dist/pypy/translator/stackless/test/test_transform.py ============================================================================== --- pypy/dist/pypy/translator/stackless/test/test_transform.py (original) +++ pypy/dist/pypy/translator/stackless/test/test_transform.py Tue May 9 11:20:42 2006 @@ -179,7 +179,29 @@ return len([x for x in range(l)]) res = llinterp_stackless_function(f) assert res == 1 - + +def test_constant_on_link(): + class A(object): + pass + def stuff(m): + if m > 100: + raise KeyError + a = A() + a.m = m + 5 + return a + def g(n, m): + a = A() + if m > 0: + try: + a = stuff(m) + except KeyError: + return -1 + n = 100 + return a.m + n + def f(): + return g(one(), one()) + res = llinterp_stackless_function(f) + assert res == 106 def rtype_stackless_function(fn): s_list_of_strings = annmodel.SomeList(ListDef(None, annmodel.SomeString())) Modified: pypy/dist/pypy/translator/stackless/transform.py ============================================================================== --- pypy/dist/pypy/translator/stackless/transform.py (original) +++ pypy/dist/pypy/translator/stackless/transform.py Tue May 9 11:20:42 2006 @@ -308,7 +308,7 @@ # does this var come from retval ? try: index1 = convertblock.inputargs.index(linkvar) - except IndexError: + except ValueError: # e.g. linkvar is a Constant continue if newblock.exits[0].args[index1] is retval: # yes From ale at codespeak.net Tue May 9 12:30:25 2006 From: ale at codespeak.net (ale at codespeak.net) Date: Tue, 9 May 2006 12:30:25 +0200 (CEST) Subject: [pypy-svn] r26993 - in pypy/dist/pypy/lib/pyontology: . test Message-ID: <20060509103025.3D03310071@code0.codespeak.net> Author: ale Date: Tue May 9 12:30:24 2006 New Revision: 26993 Modified: pypy/dist/pypy/lib/pyontology/constraint_classes.py pypy/dist/pypy/lib/pyontology/pyontology.py pypy/dist/pypy/lib/pyontology/test/test_ontology.py Log: Converted functionalporperty, symmentricproperty and inverefunctinalproperty Modified: pypy/dist/pypy/lib/pyontology/constraint_classes.py ============================================================================== --- pypy/dist/pypy/lib/pyontology/constraint_classes.py (original) +++ pypy/dist/pypy/lib/pyontology/constraint_classes.py Tue May 9 12:30:24 2006 @@ -172,10 +172,10 @@ subdom = domains[self.variable] superdom = domains[self.object] vals = superdom.getValues() - for val in subdom.getValues(): - if not val in vals: - vals.append(val) - superdom.setValues(vals) + for (key, val) in subdom.getValues(): + if not (key, val) in superdom: + for v in val: + superdom.addValue(key, v) class EquivalentPropertyConstraint(SubClassConstraint): @@ -304,11 +304,11 @@ if hasattr(dom, '_dict'): val = Linkeddict(vals) if self.variable in val.keys() and not self.object in val.keys(): - vals +=[(self.object,v) for v in val[self.variable]] - dom.setValues(vals) + vals +=[dom.addValue(self.object,v) for v in val[self.variable]] + #dom.setValues(vals) elif not self.variable in val.keys() and self.object in val.keys(): - vals +=[(self.variable,v) for v in val[self.object]] - dom.setValues(vals) + vals +=[dom.addValue(self.variable,v) for v in val[self.object]] + #dom.setValues(vals) elif self.variable in val.keys() and self.object in val.keys(): if not val[self.object] == val[self.variable]: raise ConsistencyFailure("Sameas failure: The two individuals (%s, %s) \ Modified: pypy/dist/pypy/lib/pyontology/pyontology.py ============================================================================== --- pypy/dist/pypy/lib/pyontology/pyontology.py (original) +++ pypy/dist/pypy/lib/pyontology/pyontology.py Tue May 9 12:30:24 2006 @@ -110,7 +110,7 @@ def __init__(self, name='', values=[], bases = []): ClassDomain.__init__(self, name, values, bases) - self._dict = Linkeddict() + self._dict = {} self.range = [] self.domain = [] @@ -123,7 +123,9 @@ self._dict[key].append(val) def setValues(self, values): - self._dict = Linkeddict(values) + for key, val in values: + print val + self.addValue(key, val) def removeValues(self, values): for k,v in values: @@ -168,25 +170,52 @@ def __init__(self, name='', values=[], bases = []): Property.__init__(self, name, values, bases) - self.constraint = FunctionalCardinality(name) +# self.constraint = FunctionalCardinality(name) + def addValue(self, key, val): + Property.addValue(self, key, val) + if len(self._dict[key]) > 1: + raise ConsistencyFailure("FunctionalProperties can only have one value") + class InverseFunctionalProperty(Property): def __init__(self, name='', values=[], bases = []): Property.__init__(self, name, values, bases) self.constraint = InverseFunctionalCardinality(name) + def addValue(self, key, val): + Property.addValue(self, key, val) + valuelist = [set(x) for x in self._dict.values()] + res = set() + for vals in valuelist: + if vals & res: + raise ConsistencyFailure("Only unique values in InverseFunctionalProperties") + res = res | vals + class TransitiveProperty(Property): def __init__(self, name='', values=[], bases = []): Property.__init__(self, name, values, bases) - self.constraint = TransitiveConstraint(name) + #self.constraint = TransitiveConstraint(name) + def addValue(self, key, val): + Property.addValue(self, key, val) + if val in self._dict.keys(): + for v in self._dict[val]: + Property.addValue(self, key, v) + for k in self._dict.keys(): + if key in self._dict[k]: + Property.addValue(self, k, val) + class SymmetricProperty(Property): def __init__(self, name='', values=[], bases = []): Property.__init__(self, name, values, bases) - self.constraint = SymmetricConstraint(name) +# self.constraint = SymmetricConstraint(name) + + def addValue(self, key, val): + Property.addValue(self, key, val) + Property.addValue(self, val, key) class Restriction(ClassDomain): """ A owl:restriction is an anonymous class that links a class to a restriction on a property Modified: pypy/dist/pypy/lib/pyontology/test/test_ontology.py ============================================================================== --- pypy/dist/pypy/lib/pyontology/test/test_ontology.py (original) +++ pypy/dist/pypy/lib/pyontology/test/test_ontology.py Tue May 9 12:30:24 2006 @@ -225,9 +225,8 @@ O.variables['p_'].setValues([('individ_',42)]) #assert len(O.constraints) == 2 #add another valueof the property - O.variables['p_'].setValues([('individ_',42),('individ_',43)]) + py.test.raises(ConsistencyFailure, O.variables['p_'].setValues,[('individ_',42),('individ_',43)]) #check that consistency raises - py.test.raises(ConsistencyFailure, O.consistency) def test_inversefunctionalproperty(): @@ -250,12 +249,9 @@ sub = URIRef('individ2') obj = URIRef('c') O.type(sub, obj) - O.variables['p_'].setValues([('individ_',42),('individ2_',42)]) - #check that consistency raises - py.test.raises(ConsistencyFailure, O.consistency) + py.test.raises(ConsistencyFailure, O.variables['p_'].setValues, [('individ_',42),('individ2_',42)]) def test_Transitiveproperty(): - #py.test.skip("in transit") O = Ontology() #Make functional property sub = URIRef('subRegionOf') @@ -277,9 +273,7 @@ O.consistency() assert 'Chianti_' in O.variables['subRegionOf_']._dict['Italy_'] -def test_symmetricproperty(): - #py.test.skip("in transit") - +def test_symmetricproperty(): O = Ontology() #Make functional property sub = URIRef('friend') From pedronis at codespeak.net Tue May 9 14:08:17 2006 From: pedronis at codespeak.net (pedronis at codespeak.net) Date: Tue, 9 May 2006 14:08:17 +0200 (CEST) Subject: [pypy-svn] r26994 - in pypy/dist/pypy/translator/backendopt: . test Message-ID: <20060509120817.E461B10071@code0.codespeak.net> Author: pedronis Date: Tue May 9 14:08:16 2006 New Revision: 26994 Modified: pypy/dist/pypy/translator/backendopt/propagate.py pypy/dist/pypy/translator/backendopt/test/test_propagate.py Log: fix for typo and test. Modified: pypy/dist/pypy/translator/backendopt/propagate.py ============================================================================== --- pypy/dist/pypy/translator/backendopt/propagate.py (original) +++ pypy/dist/pypy/translator/backendopt/propagate.py Tue May 9 14:08:16 2006 @@ -167,7 +167,7 @@ continue # don't fold stuff with exception handling if (block.exitswitch == c_last_exception and - i == len(block.operation) - 1): + i == len(block.operations) - 1): continue if analyzer.analyze(op): continue Modified: pypy/dist/pypy/translator/backendopt/test/test_propagate.py ============================================================================== --- pypy/dist/pypy/translator/backendopt/test/test_propagate.py (original) +++ pypy/dist/pypy/translator/backendopt/test/test_propagate.py Tue May 9 14:08:16 2006 @@ -1,6 +1,7 @@ import py from pypy.translator.translator import TranslationContext, graphof from pypy.translator.backendopt.propagate import * +from pypy.rpython.rarithmetic import ovfcheck from pypy.translator.backendopt.all import backend_optimizations from pypy.rpython.llinterp import LLInterpreter from pypy.rpython.memory.test.test_gctransform import getops @@ -122,6 +123,23 @@ assert len(graph.startblock.operations) == 0 check_graph(graph, [1], g(1), t) +def test_dont_constant_fold_exc(): + def f(x): + return 1 + def g(x): + y = f(x) + try: + return ovfcheck(1 + y) + except OverflowError: + return 0 + graph, t = get_graph(g, [int]) + constant_folding(graph, t) + if conftest.option.view: + t.view() + assert len(graph.startblock.operations) == 1 + check_graph(graph, [1], g(1), t) + + def test_constant_fold_call(): def s(x): res = 0 From ac at codespeak.net Tue May 9 18:29:38 2006 From: ac at codespeak.net (ac at codespeak.net) Date: Tue, 9 May 2006 18:29:38 +0200 (CEST) Subject: [pypy-svn] r27013 - in pypy/dist/pypy/rpython: . lltypesystem rctypes rctypes/test Message-ID: <20060509162938.B429110072@code0.codespeak.net> Author: ac Date: Tue May 9 18:29:35 2006 New Revision: 27013 Added: pypy/dist/pypy/rpython/rctypes/rcarithmetic.py (contents, props changed) pypy/dist/pypy/rpython/rctypes/test/test_rcarithmetic.py (contents, props changed) Modified: pypy/dist/pypy/rpython/lltypesystem/lltype.py pypy/dist/pypy/rpython/rarithmetic.py pypy/dist/pypy/rpython/rctypes/test/test_rprimitive.py Log: (pedronis, arre) Generalized rarithmetic to really support various integer sizes. Add rcarrithmetic that defines primitive types needed for ctypes. Generalized how to build Primitive lltypes for numbers. Added (skipped) test for missing support of proper rctypes. Modified: pypy/dist/pypy/rpython/lltypesystem/lltype.py ============================================================================== --- pypy/dist/pypy/rpython/lltypesystem/lltype.py (original) +++ pypy/dist/pypy/rpython/lltypesystem/lltype.py Tue May 9 18:29:35 2006 @@ -1,5 +1,5 @@ import py -from pypy.rpython.rarithmetic import r_uint, r_ulonglong, r_longlong +from pypy.rpython.rarithmetic import r_int, r_uint, r_ulonglong, r_longlong, base_int from pypy.rpython.objectmodel import Symbolic from pypy.tool.uid import Hashable from pypy.tool.tls import tlsobject @@ -480,16 +480,25 @@ _example = _defl +_numbertypes = {int: Primitive("Signed", 0)} +_numbertypes[r_int] = _numbertypes[int] + +def build_number(name, type): + try: + return _numbertypes[type] + except KeyError: + pass + if name is None: + raise ValueError('No matching lowlevel type for %r'%type) + number = _numbertypes[type] = Primitive(name, type()) + return number + +Signed = build_number("Signed", int) +Unsigned = build_number("Unsigned", r_uint) +SignedLongLong = build_number("SignedLongLong", r_longlong) +UnsignedLongLong = build_number("UnsignedLongLong", r_ulonglong) +Float = build_number("Float", float) -Signed = Primitive("Signed", 0) -Unsigned = Primitive("Unsigned", r_uint(0)) -if maxint == 2**31-1: - SignedLongLong = Primitive("SignedLongLong", r_longlong(0)) - UnsignedLongLong = Primitive("UnsignedLongLong", r_ulonglong(0)) -else: - SignedLongLong = Signed - UnsignedLongLong = Unsigned -Float = Primitive("Float", 0.0) Char = Primitive("Char", '\x00') Bool = Primitive("Bool", False) Void = Primitive("Void", None) @@ -539,12 +548,8 @@ return Signed if tp is bool: return Bool - if tp is r_uint: - return Unsigned - if tp is r_ulonglong: - return UnsignedLongLong - if tp is r_longlong: - return SignedLongLong + if issubclass(tp, base_int): + return build_number(None, tp) if tp is float: return Float if tp is str: Modified: pypy/dist/pypy/rpython/rarithmetic.py ============================================================================== --- pypy/dist/pypy/rpython/rarithmetic.py (original) +++ pypy/dist/pypy/rpython/rarithmetic.py Tue May 9 18:29:35 2006 @@ -17,8 +17,10 @@ catering to 2.3/2.4 differences about << ovfcheck_float_to_int convert to an integer or raise OverflowError -r_ushort like r_uint but half word size -r_ulong like r_uint but double word size +r_longlong + like r_int but double word size +r_ulonglong + like r_uint but double word size These are meant to be erased by translation, r_uint in the process should mark unsigned values, ovfcheck should @@ -81,6 +83,17 @@ return int(intp) raise OverflowError +def compute_restype(self_type, other_type): + if other_type in (int, long): + return self_type + if self_type.SIGNED != other_type.SIGNED: + raise TypeError('Can not mix %r and %r'%(self_type, other_type)) + if self_type.BITS > other_type.BITS: + return self_type + if self_type.BITS < other_type.BITS: + return other_type + return self_type + class base_int(long): """ fake unsigned integer implementation """ @@ -91,7 +104,15 @@ if one argument is int or long, the other type wins. otherwise, produce the largest class to hold the result. """ - return self.typemap[ type(self), type(other) ](value) + self_type = type(self) + other_type = type(other) + try: + return self.typemap[ self_type, other_type ](value) + except KeyError: + pass + restype = compute_restype(self_type, other_type) + self.typemap[self_type, other_type] = restype + return restype(value) def __new__(klass, val): if klass is base_int: @@ -225,7 +246,8 @@ return self._widen(other, res) class signed_int(base_int): - def __new__(klass, val): + SIGNED = True + def __new__(klass, val=0): if val > klass.MASK>>1 or val < -(klass.MASK>>1)-1: raise OverflowError("%s does not fit in signed %d-bit integer"%(val, klass.BITS)) if val < 0: @@ -234,53 +256,33 @@ typemap = {} class unsigned_int(base_int): - def __new__(klass, val): + SIGNED = False + def __new__(klass, val=0): return super(unsigned_int, klass).__new__(klass, val & klass.MASK) typemap = {} -class r_int(signed_int): - MASK = LONG_MASK - BITS = LONG_BIT - +_inttypes = {} -class r_uint(unsigned_int): - MASK = LONG_MASK - BITS = LONG_BIT - - -if LONG_BIT == 64: - r_ulonglong = r_uint - r_longlong = r_int -else: - assert LONG_BIT == 32 - - class r_longlong(signed_int): - BITS = LONG_BIT * 2 - MASK = 2**BITS-1 - - class r_ulonglong(unsigned_int): - BITS = LONG_BIT * 2 - MASK = 2**BITS-1 - -def setup_typemap(typemap, types): - for left in types: - for right in types: - if left in (int, long): - restype = right - elif right in (int, long): - restype = left - else: - if left.BITS > right.BITS: - restype = left - else: - restype = right - if restype not in (int, long): - typemap[ left, right ] = restype +def build_int(name, sign, bits): + sign = bool(sign) + try: + return _inttypes[sign, bits] + except KeyError: + pass + if sign: + int_type = signed_int + else: + int_type = unsigned_int + mask = (1 << bits) - 1 + ret = _inttypes[sign, bits] = type(name, (int_type,), {'MASK': mask, + 'BITS': bits}) + return ret -setup_typemap(unsigned_int.typemap, (int, long, r_uint, r_ulonglong)) -setup_typemap(signed_int.typemap, (int, long, r_int, r_longlong)) +r_int = build_int('r_int', True, LONG_BIT) +r_uint = build_int('r_uint', False, LONG_BIT) -del setup_typemap +r_longlong = build_int('r_longlong', True, 64) +r_ulonglong = build_int('r_ulonglong', False, 64) # string -> float helper Added: pypy/dist/pypy/rpython/rctypes/rcarithmetic.py ============================================================================== --- (empty file) +++ pypy/dist/pypy/rpython/rctypes/rcarithmetic.py Tue May 9 18:29:35 2006 @@ -0,0 +1,27 @@ +from pypy.rpython import rarithmetic +from pypy.rpython.lltypesystem import lltype +import ctypes + +def c_type_size(c_type): + bits = 0 + while c_type(1< 0 + +def test_promotion(): + assert type(rcbyte(1) + 1) is rcbyte + assert type(1 + rcbyte(1)) is rcbyte + + assert type(rcbyte(1) + rcshort(1)) is rcshort + assert type(rcshort(1) + rcbyte(1)) is rcshort + + py.test.raises(TypeError, 'rcubyte(1) + rcshort(1)') + py.test.raises(TypeError, 'rcshort(1) + rcubyte(1)') + + +def test_typeof(): + assert lltype.typeOf(rarithmetic.r_int(0)) == lltype.Signed + assert lltype.typeOf(rclong(0)) == lltype.Signed + assert lltype.Signed == CLong + assert lltype.typeOf(rarithmetic.r_uint(0)) == lltype.Unsigned + assert lltype.typeOf(rculong(0)) == lltype.Unsigned + assert lltype.Unsigned == CULong + + assert lltype.typeOf(rcbyte(0)) == CByte + assert lltype.typeOf(rcshort(0)) == CShort + + assert lltype.typeOf(rcushort(0)) == CUShort Modified: pypy/dist/pypy/rpython/rctypes/test/test_rprimitive.py ============================================================================== --- pypy/dist/pypy/rpython/rctypes/test/test_rprimitive.py (original) +++ pypy/dist/pypy/rpython/rctypes/test/test_rprimitive.py Tue May 9 18:29:35 2006 @@ -15,7 +15,7 @@ from ctypes import c_char, c_byte, c_ubyte, c_short, c_ushort, c_int, c_uint from ctypes import c_long, c_ulong, c_longlong, c_ulonglong, c_float -from ctypes import c_double, c_wchar, c_char_p, pointer +from ctypes import c_double, c_wchar, c_char_p, pointer, sizeof class Test_annotation: def test_simple(self): @@ -319,3 +319,11 @@ fn = compile(access_c_float, []) assert fn() == 5.2 + + def test_compile_short(self): + py.test.skip('In-progress') + def sizeof_c_short(): + return sizeof(c_short) + fn = compile(sizeof_c_short, []) + assert fn() == sizeof(c_short) + From stephan at codespeak.net Wed May 10 10:16:01 2006 From: stephan at codespeak.net (stephan at codespeak.net) Date: Wed, 10 May 2006 10:16:01 +0200 (CEST) Subject: [pypy-svn] r27026 - pypy/dist/pypy/module/stackless/test Message-ID: <20060510081601.1FB7210085@code0.codespeak.net> Author: stephan Date: Wed May 10 10:15:58 2006 New Revision: 27026 Added: pypy/dist/pypy/module/stackless/test/coro1.py pypy/dist/pypy/module/stackless/test/stack1.py pypy/dist/pypy/module/stackless/test/stack2.py (contents, props changed) pypy/dist/pypy/module/stackless/test/stack3.py (contents, props changed) pypy/dist/pypy/module/stackless/test/stackless_.py Log: proof of concept implementation of stackless on top of coroutine. Added: pypy/dist/pypy/module/stackless/test/coro1.py ============================================================================== --- (empty file) +++ pypy/dist/pypy/module/stackless/test/coro1.py Wed May 10 10:15:58 2006 @@ -0,0 +1,28 @@ +from stackless import coroutine + +d = {} + +def f(): + print 'in f' + +def g(coro,t): + print 'in g %s' % t + coro.switch() + +def main(): + cm = coroutine.getcurrent() + d[cm] = 'main' + cf = coroutine() + d[cf] = 'f' + print 'cf:',cf + cf.bind(f) + cg = coroutine() + d[cg] = 'g' + print 'cg:',cg + cg.bind(g,cf,'test') + cg.switch() + print 'back in main' + print d + +if __name__ == '__main__': + main() Added: pypy/dist/pypy/module/stackless/test/stack1.py ============================================================================== --- (empty file) +++ pypy/dist/pypy/module/stackless/test/stack1.py Wed May 10 10:15:58 2006 @@ -0,0 +1,18 @@ +from stackless_ import * + +def f(): + print 'in f' + +def g(t): + print 'in g %s' % t + schedule() + +def main(): + cg = tasklet(g)('test') + cf = tasklet(f)() + schedule() + print 'in main' + +if __name__ == '__main__': + main() + Added: pypy/dist/pypy/module/stackless/test/stack2.py ============================================================================== --- (empty file) +++ pypy/dist/pypy/module/stackless/test/stack2.py Wed May 10 10:15:58 2006 @@ -0,0 +1,20 @@ +from stackless_ import * + +def f(outchan): + for i in range(10): + print 'f send',i + outchan.send(i) + outchan.send(-1) + +def g(inchan): + while 1: + val = inchan.receive() + if val == -1: + break + print 'g received',val + +ch = channel() +t1 = tasklet(f)(ch) +t2 = tasklet(g)(ch) + +t1.run() Added: pypy/dist/pypy/module/stackless/test/stack3.py ============================================================================== --- (empty file) +++ pypy/dist/pypy/module/stackless/test/stack3.py Wed May 10 10:15:58 2006 @@ -0,0 +1,43 @@ +def receiver(chan, name): + while 1: + try: + data = chan.receive() + except: + print name, "** Ouch!!! **" + raise + print name, "got:", data + if data == 42: + chan.send("%s says bye" % name) + return + +import sys +import stackless +if hasattr(stackless,'coroutine'): + import stackless_ as stackless + +chan = stackless.channel() +t1 = stackless.tasklet(receiver)(chan, "inky") +t2 = stackless.tasklet(receiver)(chan, "dinky") +stackless.run() +try: + for i in 2,3,5,7, 42: + print "sending", i + chan.send(i) + chan.send(i) + #if i==7: + # print "sending Exception" + # chan.send_exception(ValueError, i) +except ValueError: + e, v, t = sys.exc_info() + print e, v + del e, v, t +print "main done." +# +# trying to clean up things, until we have a real +# channel deallocator: +print "trying cleanup:" +while chan.balance: + if chan.balance < 0: + chan.send(42) + else: + print chan.receive() Added: pypy/dist/pypy/module/stackless/test/stackless_.py ============================================================================== --- (empty file) +++ pypy/dist/pypy/module/stackless/test/stackless_.py Wed May 10 10:15:58 2006 @@ -0,0 +1,148 @@ +from stackless import coroutine + +__all__ = 'run getcurrent getmain schedule tasklet channel'.split() + +main_tasklet = None +next_tasklet = None +scheduler = None + +coro_reg = {} + +def __init(): + global maintasklet + mt = tasklet() + mt._coro = c = coroutine.getcurrent() + maintasklet = mt + coro_reg[c] = mt + +def run(): + schedule() + +def getcurrent(): + c = coroutine.getcurrent() + return coro_reg[c] + +def getmain(): + return main_tasklet + +def schedule(): + scheduler.schedule() + +class tasklet(object): + def __init__(self,func=None): + self._func = func + + def __call__(self,*argl,**argd): + self._coro = c = coroutine() + c.bind(self._func,*argl,**argd) + coro_reg[c] = self + self.insert() + return self + + def awake(self):pass + + def sleep(self):pass + + def run(self): + scheduler.setnexttask(self) + schedule() + + def insert(self): + scheduler.insert(self) + + def remove(self): + scheduler.remove(self) + + def kill(self):pass + +class channel(object): + def __init__(self): + self.balance = 0 + self._readq = [] + self._writeq = [] + + def send(self, msg): + ct = getcurrent() + scheduler.remove(ct) + self._writeq.append((ct,msg)) + self.balance += 1 + if self._readq: + nt, self._readq = self._readq[0], self._readq[1:] + scheduler.priorityinsert(nt) + schedule() + + def receive(self): + ct = getcurrent() + if self._writeq: + (wt,retval), self._writeq = self._writeq[0], self._writeq[1:] + scheduler.priorityinsert(wt) + self.balance -= 1 + return retval + else: + self._readq.append(ct) + scheduler.remove(ct) + schedule() + return self.receive() + +class Scheduler(object): + def __init__(self): + self.tasklist = [] + self.nexttask = None + + def empty(self): + return not self.tasklist + + def __str__(self): + return repr(self.tasklist) + '/%s' % self.nexttask + + def insert(self,task): + if (task not in self.tasklist) and task is not maintasklet: + self.tasklist.append(task) + if self.nexttask is None: + self.nexttask = 0 + + def priorityinsert(self,task): + if task in self.tasklist: + self.tasklist.remove(task) + if task is maintasklet: + return + if self.nexttask: + self.tasklist.insert(self.nexttask,task) + else: + self.tasklist.insert(0,task) + self.nexttask = 0 + + def remove(self,task): + try: + i = self.tasklist.index(task) + del(self.tasklist[i]) + if self.nexttask > i: + self.nexttask -= 1 + if len(self.tasklist) == 0: + self.nexttask = None + except ValueError:pass + + def next(self): + if self.nexttask is not None: + task = self.tasklist[self.nexttask] + self.nexttask += 1 + if self.nexttask == len(self.tasklist): + self.nexttask = 0 + return task + else: + return maintasklet + + def setnexttask(self,task): + if task not in self.tasklist: + self.tasklist.insert(task) + try: + i = self.tasklist.index(task) + self.nexttask = i + except IndexError:pass + + def schedule(self): + n = self.next() + n._coro.switch() + +scheduler = Scheduler() +__init() From stephan at codespeak.net Wed May 10 10:16:22 2006 From: stephan at codespeak.net (stephan at codespeak.net) Date: Wed, 10 May 2006 10:16:22 +0200 (CEST) Subject: [pypy-svn] r27027 - pypy/dist/pypy/module/stackless/test Message-ID: <20060510081622.BB9E710087@code0.codespeak.net> Author: stephan Date: Wed May 10 10:16:20 2006 New Revision: 27027 Added: pypy/dist/pypy/module/stackless/test/README Log: forgot the readme :-) Added: pypy/dist/pypy/module/stackless/test/README ============================================================================== --- (empty file) +++ pypy/dist/pypy/module/stackless/test/README Wed May 10 10:16:20 2006 @@ -0,0 +1,7 @@ +the 'tests' 'coro1.py', 'stackX.py' will only work with a pypy version that +has stackless support (translator/goal/translate.py --stackless). + +stackless_.py contains an application level proof of concept implementation of +stackless on top of stackless.coroutine. +This implementation is neither feature complete nor has it any kind of +exception handling. From ericvrp at codespeak.net Wed May 10 13:16:54 2006 From: ericvrp at codespeak.net (ericvrp at codespeak.net) Date: Wed, 10 May 2006 13:16:54 +0200 (CEST) Subject: [pypy-svn] r27045 - pypy/dist/pypy/translator/llvm Message-ID: <20060510111654.ACD3210064@code0.codespeak.net> Author: ericvrp Date: Wed May 10 13:16:53 2006 New Revision: 27045 Modified: pypy/dist/pypy/translator/llvm/buildllvm.py pypy/dist/pypy/translator/llvm/gc.py Log: Fixed translation with backend=llvm gc=none. Modified: pypy/dist/pypy/translator/llvm/buildllvm.py ============================================================================== --- pypy/dist/pypy/translator/llvm/buildllvm.py (original) +++ pypy/dist/pypy/translator/llvm/buildllvm.py Wed May 10 13:16:53 2006 @@ -35,8 +35,6 @@ opts += "-globalopt -constmerge -ipsccp -deadargelim -inline " \ "-instcombine -scalarrepl -globalsmodref-aa -licm -load-vn " \ "-gcse -instcombine -simplifycfg -globaldce " - if use_gcc: - opts += "-inline-threshold=100 " return opts def compile_module(module, source_files, object_files, library_files): @@ -60,6 +58,9 @@ pyxfile=None, optimize=True, exe_name=None, profile=False, cleanup=False, use_gcc=True): + if exe_name: + use_gcc = False #XXX trying to get of gcc (at least for standalones) + # where we are building dirpath = llvmfile.dirpath() @@ -92,6 +93,8 @@ if not use_gcc: llc_params = llvm_version() > 1.6 and '-enable-x86-fastcc' or '' + if llc_params and exe_name: + llc_params += ' -relocation-model=static' #XXX while llvm jumptables not with PIC cmds.append("llc %s %s %s.bc -f -o %s.s" % (llc_params, genllvm.db.exceptionpolicy.llc_options(), b, b)) cmds.append("as %s.s -o %s.o" % (b, b)) @@ -102,7 +105,7 @@ else: cmds.append("llc %s %s.bc -march=c -f -o %s.c" % (genllvm.db.exceptionpolicy.llc_options(), b, b)) if exe_name: - cmd = "gcc %s.c -c -O3 -fno-inline -pipe" % b + cmd = "gcc %s.c -c -O3 -pipe" % b if profile: cmd += ' -pg' else: Modified: pypy/dist/pypy/translator/llvm/gc.py ============================================================================== --- pypy/dist/pypy/translator/llvm/gc.py (original) +++ pypy/dist/pypy/translator/llvm/gc.py Wed May 10 13:16:53 2006 @@ -20,6 +20,9 @@ def malloc(self, codewriter, targetvar, type_, size=1, atomic=False): raise NotImplementedError, 'GcPolicy should not be used directly' + def var_malloc(self, codewriter, targetvar, type_, node, len, atomic=False): + raise NotImplementedError, 'GcPolicy should not be used directly' + def new(db, gcpolicy=None): """ factory """ gcpolicy = gcpolicy or 'boehm' @@ -37,21 +40,33 @@ gcpolicy = BoehmGcPolicy(db) elif gcpolicy == 'ref': gcpolicy = RefcountingGcPolicy(db) - elif gcpolicy == 'raw': + elif gcpolicy in ('none', 'raw'): gcpolicy = RawGcPolicy(db) else: raise Exception, 'unknown gcpolicy: ' + str(gcpolicy) return gcpolicy new = staticmethod(new) + class RawGcPolicy(GcPolicy): def __init__(self, db): - self.db = db + self.boehm = BoehmGcPolicy(db) + + def malloc(self, codewriter, targetvar, type_, size=1, atomic=False, exc_flag=False): + return self.boehm.malloc(codewriter, targetvar, type_, size, atomic, exc_flag) + + def var_malloc(self, codewriter, targetvar, type_, node, len, atomic=False): + return self.boehm.var_malloc(codewriter, targetvar, type_, node, len, atomic) + + def genextern_code(self): + r = '' + r += '#define __GC_STARTUP_CODE__\n' + r += '#define __GC_SETUP_CODE__\n' + r += 'char* pypy_malloc(int size) { return calloc(1, size); }\n' + r += 'char* pypy_malloc_atomic(int size) { return calloc(1, size); }\n' + return r + - def malloc(self, codewriter, targetvar, type_, size=1, atomic=False): - codewriter.malloc(targetvar, type_, size) - #XXX memset - class BoehmGcPolicy(GcPolicy): def __init__(self, db, exc_useringbuf=False): @@ -171,6 +186,7 @@ targetvar, indices_to_arraylength) codewriter.store(lentype, len, arraylength) + class RefcountingGcPolicy(GcPolicy): def __init__(self, db): raise NotImplementedError, 'RefcountingGcPolicy' From ericvrp at codespeak.net Wed May 10 13:18:44 2006 From: ericvrp at codespeak.net (ericvrp at codespeak.net) Date: Wed, 10 May 2006 13:18:44 +0200 (CEST) Subject: [pypy-svn] r27046 - pypy/dist/pypy/translator/goal Message-ID: <20060510111844.8C88910064@code0.codespeak.net> Author: ericvrp Date: Wed May 10 13:18:43 2006 New Revision: 27046 Modified: pypy/dist/pypy/translator/goal/bench-cronjob.py pypy/dist/pypy/translator/goal/bench-unix.py Log: Benchmarking some (llvm) llc options Modified: pypy/dist/pypy/translator/goal/bench-cronjob.py ============================================================================== --- pypy/dist/pypy/translator/goal/bench-cronjob.py (original) +++ pypy/dist/pypy/translator/goal/bench-cronjob.py Wed May 10 13:18:43 2006 @@ -3,8 +3,10 @@ import autopath import py import time, os, sys, stat +from pypy.translator.llvm.buildllvm import optimizations homedir = os.getenv('HOME') +tmpdir = py.std.tempfile.gettempdir() + '/usession-' + os.environ['USER'] + '/' def update_pypy(): os.chdir(homedir + '/projects/pypy-dist') @@ -13,39 +15,43 @@ def update_llvm(): os.chdir(homedir + '/projects/llvm') os.system('cvs -q up 2>&1') - #os.system('make clean 2>&1') - os.system('make -j3 tools-only 2>&1') + os.system('make -k -j3 tools-only 2>&1') def compile_llvm_variants(revision): - tmpdir = py.std.tempfile.gettempdir() + '/usession-' + os.environ['USER'] + '/' + ll2bc(revision) + bc2x86_exe(revision, 'x86A', '-enable-x86-fastcc -relocation-model=static -join-liveintervals') + bc2x86_exe(revision, 'x86B', '-relocation-model=static') + bc2x86_exe(revision, 'x86C', '') + bc2c_exe(revision) - cmd = 'cp %sentry_point.ll pypy/translator/goal/entry_point-%s.ll' % (tmpdir, revision) + +def ll2bc(revision): + cmd = 'cp %spypy.ll pypy/translator/goal/archive/pypy-%s.ll' % (tmpdir, revision) print cmd os.system(cmd) - cmd = "rm pypy/translator/goal/pypy-llvm-" + revision + opts = optimizations(simple=False, use_gcc=False) + cmd = '~/bin/llvm-as < %spypy.ll | ~/bin/opt %s -f -o %spypy.bc' % ( + tmpdir, opts, tmpdir) print cmd os.system(cmd) - ll2bc(tmpdir) - bc2c_exe(tmpdir, revision) - bc2x86_exe(tmpdir, revision, 'x86' , '') - #bc2x86_exe(tmpdir, revision, 'x86dag', '-enable-x86-dag-isel') + cmd = 'cp %spypy.bc pypy/translator/goal/archive/pypy-%s.bc' % (tmpdir, revision) + print cmd + os.system(cmd) -def ll2bc(tmpdir): - cmd = '~/bin/llvm-as < %sentry_point.ll | ~/bin/opt -verify -lowersetjmp -funcresolve -raiseallocs -simplifycfg -mem2reg -globalopt -globaldce -ipconstprop -deadargelim -instcombine -simplifycfg -basiccg -prune-eh -inline -simplify-libcalls -basiccg -argpromotion -raise -tailduplicate -simplifycfg -scalarrepl -instcombine -break-crit-edges -condprop -tailcallelim -simplifycfg -reassociate -loopsimplify -licm -instcombine -indvars -loop-unroll -instcombine -load-vn -gcse -sccp -instcombine -break-crit-edges -condprop -dse -mergereturn -adce -simplifycfg -deadtypeelim -constmerge -verify -globalopt -constmerge -ipsccp -deadargelim -inline -instcombine -scalarrepl -globalsmodref-aa -licm -load-vn -gcse -instcombine -simplifycfg -globaldce -f -o %sentry_point_llvm1_7.bc' % (tmpdir, tmpdir) +def bc2c_exe(revision): + b = "%spypy-llvm-%s-c" % (tmpdir, revision) + cmd = "~/bin/llc %spypy.bc -march=c -f -o %s.c" % (tmpdir, b) print cmd os.system(cmd) - -def bc2c_exe(tmpdir, revision): - b = "%spypy-llvm-%s-llvm1_7_c" % (tmpdir, revision) - cmd = "~/bin/llc %sentry_point_llvm1_7.bc -march=c -f -o %s.c" % (tmpdir, b) + cmd = "gcc %s.c -S -O3 -fomit-frame-pointer -o %s.s" % (b, b) print cmd os.system(cmd) - cmd = "gcc %s.c -O2 -fomit-frame-pointer -static -lgc -lm -lpthread -pipe -o %s" % (b, b) + cmd = "gcc %s.s -static -lgc -lm -lpthread -pipe -o %s" % (b, b) print cmd os.system(cmd) @@ -54,17 +60,21 @@ os.system(cmd) -def bc2x86_exe(tmpdir, revision, name_extra, llc_extra_options): - b = "%spypy-llvm-%s-llvm1_7_%s" % (tmpdir, revision, name_extra) - cmd = "~/bin/llc %sentry_point_llvm1_7.bc %s -f -o %s.s" % (tmpdir, llc_extra_options, b) +def bc2x86_exe(revision, name_extra, llc_extra_options): + b = "%spypy-llvm-%s-%s" % (tmpdir, revision, name_extra) + cmd = "~/bin/llc %spypy.bc %s -f -o %s.s" % (tmpdir, llc_extra_options, b) print cmd os.system(cmd) - cmd = "as %s.s -o %s.o" % (b, b) + cmd = 'cp %s.s pypy/translator/goal/archive' % b print cmd os.system(cmd) - cmd = "gcc %s.o -static -lgc -lm -lpthread -pipe -o %s" % (b, b) + #cmd = "as %s.s -o %s.o" % (b, b) + #print cmd + #os.system(cmd) + + cmd = "gcc %s.s -static -lgc -lm -lpthread -pipe -o %s" % (b, b) print cmd os.system(cmd) @@ -76,13 +86,22 @@ def compile(backend): try: backend, features = backend.split('--', 1) - featureoptions = ''.join([" --" + f for f in features.split('--')]) + featureoptions = ''.join([" --" + f for f in features.split('--') if f[0] != '_']) + targetoptions = ''.join([" --" + f[1:] for f in features.split('--') if f[0] == '_']) except: features = '' featureoptions = '' + targetoptions = '' + + if backend == 'llvm': + translateoptions = ' --source' + else: + translateoptions = '' os.chdir(homedir + '/projects/pypy-dist/pypy/translator/goal') - os.system('/usr/local/bin/python translate.py --backend=%(backend)s%(featureoptions)s --text --batch targetpypystandalone.py 2>&1' % locals()) + #os.system('cp ~/x/entry_point.ll %s/entry_point.ll' % tmpdir) #XXX + os.system('/usr/local/bin/python translate.py --backend=%(backend)s%(featureoptions)s%(translateoptions)s --text --batch targetpypystandalone.py %(targetoptions)s 2>&1' % locals()) + os.system('mv %s/entry_point.ll %s/pypy.ll' % (tmpdir, tmpdir)) os.chdir(homedir + '/projects/pypy-dist') try: @@ -94,18 +113,18 @@ if features: realname += "-" + features - pypy = open(basename, 'rb').read() - if len(pypy) > 0: - open(realname, 'wb').write(pypy) - os.chmod(realname, stat.S_IRWXU) - os.unlink(basename) - - if backend == 'llvm': + if backend == 'llvm': #create llvm exectutable from the current source compile_llvm_variants(revision) + else: #copy executable + pypy = open(basename, 'rb').read() + if len(pypy) > 0: + open(realname, 'wb').write(pypy) + os.chmod(realname, stat.S_IRWXU) + os.unlink(basename) def benchmark(): - os.system('cat /proc/cpuinfo') - os.system('free') + #os.system('cat /proc/cpuinfo') + #os.system('free') os.chdir(homedir + '/projects/pypy-dist/pypy/translator/goal') os.system('/usr/local/bin/python bench-unix.py 2>&1 | tee benchmark.txt' % locals()) os.system('echo "
"    >  benchmark.html')
@@ -114,8 +133,10 @@
     os.system('scp benchmark.html ericvrp at codespeak.net:public_html/benchmark/index.html')
 
 def main(backends=[]):
-    if backends == []:
-        backends = 'llvm c c--stackless'.split()
+    if backends == []:  #_ prefix means target specific option
+        backends = 'llvm c c--gc=framework c--stackless c--_thread c--stackless--_thread'.split()
+        #backends = 'llvm c c--stackless c--_thread c--stackless--_thread'.split()
+        #backends = 'llvm c c--stackless c--gc=ref c--gc=ref--stackless c--_thread c--gc=ref--_thread'.split()
     print time.ctime()
     if 'llvm' in backends:
         update_llvm()
@@ -124,6 +145,7 @@
         try:
             compile(backend)
         except:
+            raise
             pass
     benchmark()
     print time.ctime()

Modified: pypy/dist/pypy/translator/goal/bench-unix.py
==============================================================================
--- pypy/dist/pypy/translator/goal/bench-unix.py	(original)
+++ pypy/dist/pypy/translator/goal/bench-unix.py	Wed May 10 13:18:43 2006
@@ -71,7 +71,7 @@
     txt = run_cmd('%s -c "%s"' % (executable, argstr))
     return get_result(txt, PYSTONE_PATTERN)
 
-def run_richards(executable='/usr/local/bin/python', n=10):
+def run_richards(executable='/usr/local/bin/python', n=5):
     argstr = RICHARDS_CMD % n
     txt = run_cmd('%s -c "%s"' % (executable, argstr))
     return get_result(txt, RICHARDS_PATTERN)
@@ -80,7 +80,7 @@
     exes = []
     for exe in [os.path.join('.', name) for name in os.listdir('.') if name.startswith('pypy-')]:
         try:
-            exes.append( (exe.split('-',2)[2], exe) )
+            exes.append( (exe.split('-')[2], exe) )
         except:
             pass    #skip filenames without version number
     exes.sort()


From stephan at codespeak.net  Wed May 10 13:31:13 2006
From: stephan at codespeak.net (stephan at codespeak.net)
Date: Wed, 10 May 2006 13:31:13 +0200 (CEST)
Subject: [pypy-svn] r27047 - in pypy/dist/pypy: module/stackless
	objspace/std objspace/std/test
Message-ID: <20060510113113.DCD6810064@code0.codespeak.net>

Author: stephan
Date: Wed May 10 13:31:10 2006
New Revision: 27047

Added:
   pypy/dist/pypy/objspace/std/test/test_set.py
Modified:
   pypy/dist/pypy/module/stackless/__init__.py
   pypy/dist/pypy/objspace/std/frozensettype.py
   pypy/dist/pypy/objspace/std/model.py
   pypy/dist/pypy/objspace/std/objspace.py
   pypy/dist/pypy/objspace/std/setobject.py
   pypy/dist/pypy/objspace/std/settype.py
Log:
removed the WITHSET switch.


Modified: pypy/dist/pypy/module/stackless/__init__.py
==============================================================================
--- pypy/dist/pypy/module/stackless/__init__.py	(original)
+++ pypy/dist/pypy/module/stackless/__init__.py	Wed May 10 13:31:10 2006
@@ -10,7 +10,7 @@
     }
 
     interpleveldefs = {
-        'tasklet'    : 'interp_stackless.tasklet',
+        #'tasklet'    : 'interp_stackless.tasklet',
         'coroutine'  : 'coroutine.AppCoroutine',
     }
 

Modified: pypy/dist/pypy/objspace/std/frozensettype.py
==============================================================================
--- pypy/dist/pypy/objspace/std/frozensettype.py	(original)
+++ pypy/dist/pypy/objspace/std/frozensettype.py	Wed May 10 13:31:10 2006
@@ -4,7 +4,6 @@
 from pypy.objspace.std.stdtypedef import StdObjSpaceMultiMethod as SMM
 from pypy.interpreter.gateway import NoneNotWrapped
 from pypy.interpreter import gateway
-from pypy.objspace.std.model import WITHSET
 
 frozenset_copy                  = SMM('copy', 1)
 frozenset_difference            = SMM('difference', 2)
@@ -23,7 +22,7 @@
     if _is_frozenset_exact(w_iterable):
         return w_iterable
     w_obj = space.allocate_instance(W_FrozensetObject, w_frozensettype)
-    W_FrozensetObject.__init__(w_obj, None)
+    W_FrozensetObject.__init__(w_obj, space, None)
 
     return w_obj
 

Modified: pypy/dist/pypy/objspace/std/model.py
==============================================================================
--- pypy/dist/pypy/objspace/std/model.py	(original)
+++ pypy/dist/pypy/objspace/std/model.py	Wed May 10 13:31:10 2006
@@ -8,7 +8,6 @@
 import pypy.interpreter.pycode
 import pypy.interpreter.special
 
-WITHSET = False
 WITHSMALLINT = False
 
 class StdTypeModel:
@@ -22,9 +21,8 @@
             from pypy.objspace.std.inttype    import int_typedef
             from pypy.objspace.std.floattype  import float_typedef
             from pypy.objspace.std.complextype  import complex_typedef
-            if WITHSET:
-                from pypy.objspace.std.settype import set_typedef
-                from pypy.objspace.std.frozensettype import frozenset_typedef
+            from pypy.objspace.std.settype import set_typedef
+            from pypy.objspace.std.frozensettype import frozenset_typedef
             from pypy.objspace.std.tupletype  import tuple_typedef
             from pypy.objspace.std.listtype   import list_typedef
             from pypy.objspace.std.dicttype   import dict_typedef
@@ -48,8 +46,7 @@
         from pypy.objspace.std import intobject
         from pypy.objspace.std import floatobject
         from pypy.objspace.std import complexobject
-        if WITHSET:
-            from pypy.objspace.std import setobject
+        from pypy.objspace.std import setobject
         if WITHSMALLINT:
             from pypy.objspace.std import smallintobject
         from pypy.objspace.std import tupleobject
@@ -91,10 +88,9 @@
             pypy.interpreter.special.Ellipsis: [],
             }
         self.typeorder[complexobject.W_ComplexObject] = []
-        if WITHSET:
-            self.typeorder[setobject.W_SetObject] = []
-            self.typeorder[setobject.W_FrozensetObject] = []
-            self.typeorder[setobject.W_SetIterObject] = []
+        self.typeorder[setobject.W_SetObject] = []
+        self.typeorder[setobject.W_FrozensetObject] = []
+        self.typeorder[setobject.W_SetIterObject] = []
         if WITHSMALLINT:
             self.typeorder[smallintobject.W_SmallIntObject] = []
         for type in self.typeorder:

Modified: pypy/dist/pypy/objspace/std/objspace.py
==============================================================================
--- pypy/dist/pypy/objspace/std/objspace.py	(original)
+++ pypy/dist/pypy/objspace/std/objspace.py	Wed May 10 13:31:10 2006
@@ -7,7 +7,6 @@
 from pypy.tool.cache import Cache 
 from pypy.tool.sourcetools import func_with_new_name
 from pypy.objspace.std.model import W_Object, UnwrapError
-from pypy.objspace.std.model import WITHSET
 from pypy.objspace.std.model import W_ANY, StdObjSpaceMultiMethod, StdTypeModel
 from pypy.objspace.std.multimethod import FailedToImplement
 from pypy.objspace.descroperation import DescrOperation
@@ -301,14 +300,12 @@
             return W_ComplexObject(x.real, x.imag)
 
         if isinstance(x, set):
-            if WITHSET:
-                wrappeditems = [self.wrap(item) for item in x]
-                return W_SetObject(wrappeditems)
+            wrappeditems = [self.wrap(item) for item in x]
+            return W_SetObject(self, wrappeditems)
 
         if isinstance(x, frozenset):
-            if WITHSET:
-                wrappeditems = [self.wrap(item) for item in x]
-                return W_FrozensetObject(wrappeditems)
+            wrappeditems = [self.wrap(item) for item in x]
+            return W_FrozensetObject(self, wrappeditems)
 
         if x is __builtin__.Ellipsis:
             # '__builtin__.Ellipsis' avoids confusion with special.Ellipsis
@@ -356,12 +353,11 @@
     def newcomplex(self, realval, imagval):
         return W_ComplexObject(realval, imagval)
 
-    if WITHSET:
-        def newset(self, rdict_w):
-            return W_SetObject(rdict_w)
+    def newset(self, rdict_w):
+        return W_SetObject(self, rdict_w)
 
-        def newfrozenset(self, rdict_w):
-            return W_FrozensetObject(rdict_w)
+    def newfrozenset(self, rdict_w):
+        return W_FrozensetObject(self, rdict_w)
 
     def newlong(self, val): # val is an int
         return W_LongObject.fromint(self, val)

Modified: pypy/dist/pypy/objspace/std/setobject.py
==============================================================================
--- pypy/dist/pypy/objspace/std/setobject.py	(original)
+++ pypy/dist/pypy/objspace/std/setobject.py	Wed May 10 13:31:10 2006
@@ -1,6 +1,5 @@
 from pypy.objspace.std.objspace import W_Object, OperationError
 from pypy.objspace.std.objspace import registerimplementation, register_all
-from pypy.objspace.std.model import WITHSET
 from pypy.objspace.std.stdtypedef import StdObjSpaceMultiMethod
 from pypy.rpython.objectmodel import r_dict
 from pypy.rpython.rarithmetic import intmask, r_uint
@@ -8,7 +7,7 @@
 
 class W_BaseSetObject(W_Object):
 
-    def __init__(w_self, setdata=None):
+    def __init__(w_self, space, setdata=None):
         if setdata is None:
             w_self.setdata = r_dict(space.eq_w, space.hash_w)
         else:
@@ -23,9 +22,9 @@
         #return space.call(space.type(w_self),W_SetIterObject(rdict_w))
         objtype = type(w_self)
         if objtype is W_SetObject:
-            obj = W_SetObject(rdict_w)
+            obj = W_SetObject(space, rdict_w)
         elif objtype is W_FrozensetObject:
-            obj = W_FrozensetObject(rdict_w)
+            obj = W_FrozensetObject(space, rdict_w)
         else:
             itemiterator = space.iter(W_SetIterObject(rdict_w))
             obj = space.call_function(space.type(w_self),itemiterator)
@@ -37,8 +36,8 @@
 class W_FrozensetObject(W_BaseSetObject):
     from pypy.objspace.std.frozensettype import frozenset_typedef as typedef
 
-    def __init__(w_self, setdata):
-        W_BaseSetObject.__init__(w_self, setdata)
+    def __init__(w_self, space, setdata):
+        W_BaseSetObject.__init__(w_self, space, setdata)
         w_self.hash = -1
 
 registerimplementation(W_SetObject)

Modified: pypy/dist/pypy/objspace/std/settype.py
==============================================================================
--- pypy/dist/pypy/objspace/std/settype.py	(original)
+++ pypy/dist/pypy/objspace/std/settype.py	Wed May 10 13:31:10 2006
@@ -1,10 +1,9 @@
 from pypy.interpreter.error import OperationError
 from pypy.objspace.std.objspace import register_all
-from pypy.objspace.std.stdtypedef import StdTypeDef, newmethod
+from pypy.objspace.std.stdtypedef import StdTypeDef, newmethod, no_hash_descr
 from pypy.objspace.std.stdtypedef import StdObjSpaceMultiMethod as SMM
 from pypy.interpreter.gateway import NoneNotWrapped
 from pypy.interpreter import gateway
-from pypy.objspace.std.model import WITHSET
 
 set_add                         = SMM('add', 2)
 set_clear                       = SMM('clear', 1)
@@ -29,7 +28,7 @@
 def descr__new__(space, w_settype, __args__):
     from pypy.objspace.std.setobject import W_SetObject
     w_obj = space.allocate_instance(W_SetObject, w_settype)
-    W_SetObject.__init__(w_obj, None)
+    W_SetObject.__init__(w_obj, space, None)
     return w_obj
 
 set_typedef = StdTypeDef("set",

Added: pypy/dist/pypy/objspace/std/test/test_set.py
==============================================================================
--- (empty file)
+++ pypy/dist/pypy/objspace/std/test/test_set.py	Wed May 10 13:31:10 2006
@@ -0,0 +1,56 @@
+"""
+The main test for the set implementation is located
+at:
+    pypy-dist/lib-python/modified-2.4.1/test/test_set.py
+    go there and invoke
+    ../../../pypy/bin/py.py test_set.py
+This file just contains some basic tests that make sure, the implementation
+is not too wrong.
+"""
+import autopath
+import py.test
+from pypy.objspace.std.setobject import W_SetObject, W_FrozensetObject
+from pypy.objspace.std.setobject import _initialize_set
+from pypy.objspace.std.setobject import set_intersection__Set_Set
+from pypy.objspace.std.setobject import set_intersection__Set_ANY
+from pypy.objspace.std.setobject import eq__Set_Set
+
+letters = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ'
+
+class W_SubSetObject(W_SetObject):pass
+
+class TestW_SetObject:
+
+    def setup_method(self, method):
+        self.word = self.space.wrap('simsalabim')
+        self.otherword = self.space.wrap('madagascar')
+        self.letters = self.space.wrap(letters)
+        self.true = self.space.w_True
+        self.false = self.space.w_False
+
+    def test_and(self):
+        s = W_SetObject(self.space, None)
+        _initialize_set(self.space, s, self.word)
+        t0 = W_SetObject(self.space, None)
+        _initialize_set(self.space, t0, self.otherword)
+        t1 = W_FrozensetObject(self.space, None)
+        _initialize_set(self.space, t1, self.otherword)
+        r0 = set_intersection__Set_Set(self.space, s, t0)
+        r1 = set_intersection__Set_Set(self.space, s, t1)
+        assert eq__Set_Set(self.space, r0, r1) == self.true
+        sr = set_intersection__Set_ANY(self.space, s, self.otherword)
+        assert eq__Set_Set(self.space, r0, sr) == self.true
+
+    def test_compare(self):
+        s = W_SetObject(self.space, None)
+        _initialize_set(self.space, s, self.word)
+        t = W_SetObject(self.space, None)
+        _initialize_set(self.space, t, self.word)
+        assert self.space.eq_w(s,t)
+
+class AppTestAppSetTest:
+    def test_subtype(self):
+        class subset(set):pass
+        a = subset()
+        b = a | set('abc')
+        assert type(b) is subset


From ericvrp at codespeak.net  Wed May 10 14:16:47 2006
From: ericvrp at codespeak.net (ericvrp at codespeak.net)
Date: Wed, 10 May 2006 14:16:47 +0200 (CEST)
Subject: [pypy-svn] r27048 - in pypy/dist/pypy/translator/llvm: . pyllvm
Message-ID: <20060510121647.50F8210085@code0.codespeak.net>

Author: ericvrp
Date: Wed May 10 14:16:44 2006
New Revision: 27048

Modified:
   pypy/dist/pypy/translator/llvm/database.py
   pypy/dist/pypy/translator/llvm/funcnode.py
   pypy/dist/pypy/translator/llvm/pyllvm/cc.py
Log:
genllvm is trying to get a free ride on genc's exception transform


Modified: pypy/dist/pypy/translator/llvm/database.py
==============================================================================
--- pypy/dist/pypy/translator/llvm/database.py	(original)
+++ pypy/dist/pypy/translator/llvm/database.py	Wed May 10 14:16:44 2006
@@ -14,6 +14,7 @@
 from pypy.objspace.flow.model import Constant, Variable
 from pypy.rpython.memory.lladdress import NULL
 from pypy.rpython.objectmodel import Symbolic, ComputedIntSymbolic
+from pypy.translator.c.exceptiontransform import ExceptionTransformer
 
 log = log.database 
 
@@ -30,6 +31,11 @@
 
         self.primitives_init()
 
+        if translator is None or translator.rtyper is None:
+            self.exctransformer = None
+        else:
+            self.exctransformer = ExceptionTransformer(translator)
+
     def primitives_init(self):
         primitives = {
             lltype.Char: "sbyte",

Modified: pypy/dist/pypy/translator/llvm/funcnode.py
==============================================================================
--- pypy/dist/pypy/translator/llvm/funcnode.py	(original)
+++ pypy/dist/pypy/translator/llvm/funcnode.py	Wed May 10 14:16:44 2006
@@ -44,6 +44,19 @@
         #from pypy.translator.llvm.backendopt.mergemallocs import merge_mallocs
         #merge_mallocs(self.db.translator, self.graph, self.ref)
 
+        # apply the stackless transformation
+        #if db.stacklesstransformer and do_stackless:
+        #    db.stacklesstransformer.transform_graph(graph)
+
+        # apply the exception transformation
+        #if self.db.exctransformer:
+        #    self.db.exctransformer.create_exception_handling(self.graph)
+
+        # apply the gc transformation
+        #self.db.gctransformer.transform_graph(self.graph)
+
+        #self.graph.show()
+
     def __str__(self):
         return "" %(self.ref,)
     

Modified: pypy/dist/pypy/translator/llvm/pyllvm/cc.py
==============================================================================
--- pypy/dist/pypy/translator/llvm/pyllvm/cc.py	(original)
+++ pypy/dist/pypy/translator/llvm/pyllvm/cc.py	Wed May 10 14:16:44 2006
@@ -8,7 +8,11 @@
         d = __file__[:__file__.find("pyllvm")] + "llvmcapi/"
         #XXX does this load once or every time?
         try:
-            self.library  = cdll.load(d + libname + ".so")
+            if "load" in dir(cdll):
+                cdll_load = cdll.load
+            else:
+                cdll_load = cdll.LoadLibrary
+            self.library  = cdll_load(d + libname + ".so")
         except:
             raise Exception("llvmcapi not found: run 'python setup.py build_ext -i' in " + d)
         self.restype  = restype


From ac at codespeak.net  Wed May 10 14:22:23 2006
From: ac at codespeak.net (ac at codespeak.net)
Date: Wed, 10 May 2006 14:22:23 +0200 (CEST)
Subject: [pypy-svn] r27049 - in pypy/dist/pypy: annotation rpython
	rpython/rctypes/test translator/stackless
Message-ID: <20060510122223.9ED1510085@code0.codespeak.net>

Author: ac
Date: Wed May 10 14:22:20 2006
New Revision: 27049

Modified:
   pypy/dist/pypy/annotation/binaryop.py
   pypy/dist/pypy/annotation/bookkeeper.py
   pypy/dist/pypy/annotation/builtin.py
   pypy/dist/pypy/annotation/model.py
   pypy/dist/pypy/annotation/unaryop.py
   pypy/dist/pypy/rpython/rarithmetic.py
   pypy/dist/pypy/rpython/rctypes/test/test_rcarithmetic.py
   pypy/dist/pypy/rpython/rint.py
   pypy/dist/pypy/translator/stackless/transform.py
Log:
(pedronis, arre) Remove the size attribute of SomeInteger in preparation to support more integer types.

Modified: pypy/dist/pypy/annotation/binaryop.py
==============================================================================
--- pypy/dist/pypy/annotation/binaryop.py	(original)
+++ pypy/dist/pypy/annotation/binaryop.py	Wed May 10 14:22:20 2006
@@ -20,7 +20,7 @@
 from pypy.annotation.bookkeeper import getbookkeeper
 from pypy.objspace.flow.model import Variable
 from pypy.annotation.listdef import ListDef
-from pypy.rpython import extregistry
+from pypy.rpython import extregistry, rarithmetic
 
 # convenience only!
 def immutablevalue(x):
@@ -225,10 +225,9 @@
     # unsignedness is considered a rare and contagious disease
 
     def union((int1, int2)):
-        unsigned = int1.unsigned or int2.unsigned
-        return SomeInteger(nonneg = unsigned or (int1.nonneg and int2.nonneg),
-                           unsigned=unsigned,
-                           size = max(int1.size, int2.size))
+        knowntype = rarithmetic.compute_restype(int1.knowntype, int2.knowntype)
+        return SomeInteger(nonneg=int1.nonneg and int2.nonneg,
+                           knowntype=knowntype)
 
     or_ = xor = add = mul = _clone(union, [])
     add_ovf = mul_ovf = _clone(union, [OverflowError])
@@ -241,33 +240,28 @@
     truediv_ovf = _clone(truediv, [ZeroDivisionError, OverflowError])
 
     def sub((int1, int2)):
-        return SomeInteger(unsigned = int1.unsigned or int2.unsigned,
-                           size = max(int1.size, int2.size))
+        knowntype = rarithmetic.compute_restype(int1.knowntype, int2.knowntype)
+        return SomeInteger(knowntype=knowntype)
     sub.can_only_throw = []
     sub_ovf = _clone(sub, [OverflowError])
 
     def and_((int1, int2)):
-        unsigned = int1.unsigned or int2.unsigned
-        return SomeInteger(nonneg = unsigned or int1.nonneg or int2.nonneg,
-                           unsigned = unsigned,
-                           size = max(int1.size, int2.size))
+        knowntype = rarithmetic.compute_restype(int1.knowntype, int2.knowntype)
+        return SomeInteger(nonneg=int1.nonneg and int2.nonneg,
+                           knowntype=knowntype)
     and_.can_only_throw = []
 
     def lshift((int1, int2)):
-        if int1.unsigned:
-            return SomeInteger(unsigned=True)
-        return SomeInteger(nonneg = int1.nonneg,
-                           size = max(int1.size, int2.size))
+        return SomeInteger(knowntype=int1.knowntype)
+
     lshift.can_only_throw = [ValueError]
     rshift = lshift
     lshift_ovf = _clone(lshift, [ValueError, OverflowError])
 
     def pow((int1, int2), obj3):
-        if int1.unsigned or int2.unsigned or getattr(obj3, 'unsigned', False):
-            return SomeInteger(unsigned=True,
-                               size = max(int1.size, int2.size))
+        knowntype = rarithmetic.compute_restype(int1.knowntype, int2.knowntype)
         return SomeInteger(nonneg = int1.nonneg,
-                           size = max(int1.size, int2.size))
+                           knowntype=knowntype)
     pow.can_only_throw = [ZeroDivisionError]
     pow_ovf = _clone(pow, [ZeroDivisionError, OverflowError])
 

Modified: pypy/dist/pypy/annotation/bookkeeper.py
==============================================================================
--- pypy/dist/pypy/annotation/bookkeeper.py	(original)
+++ pypy/dist/pypy/annotation/bookkeeper.py	Wed May 10 14:22:20 2006
@@ -315,9 +315,9 @@
         elif tp is r_uint:
             result = SomeInteger(nonneg = True, unsigned = True)
         elif tp is r_ulonglong:
-            result = SomeInteger(nonneg = True, unsigned = True, size = 2)
+            result = SomeInteger(nonneg = True, knowntype=r_ulonglong)
         elif tp is r_longlong:
-            result = SomeInteger(nonneg = x>=0, size = 2)
+            result = SomeInteger(nonneg = x>=0, knowntype=r_longlong)
         elif issubclass(tp, str): # py.lib uses annotated str subclasses
             if len(x) == 1:
                 result = SomeChar()
@@ -503,11 +503,11 @@
         elif t is int or t is r_int:
             return SomeInteger()
         elif t is r_uint:
-            return SomeInteger(nonneg = True, unsigned = True)
+            return SomeInteger(unsigned = True)
         elif t is r_ulonglong or t is base_int:
-            return SomeInteger(nonneg = True, unsigned = True, size = 2)
+            return SomeInteger(knowntype=r_ulonglong)
         elif t is r_longlong:
-            return SomeInteger(size = 2)
+            return SomeInteger(knowntype=r_longlong)
         elif issubclass(t, str): # py.lib uses annotated str subclasses
             return SomeString()
         elif t is float:

Modified: pypy/dist/pypy/annotation/builtin.py
==============================================================================
--- pypy/dist/pypy/annotation/builtin.py	(original)
+++ pypy/dist/pypy/annotation/builtin.py	Wed May 10 14:22:20 2006
@@ -87,11 +87,11 @@
 
 def restricted_longlong(s_obj):    # for r_uint
     return constpropagate(pypy.rpython.rarithmetic.r_longlong, [s_obj],
-                          SomeInteger(size=2))
+                          SomeInteger(knowntype=pypy.rpython.rarithmetic.r_longlong))
 
 def restricted_ulonglong(s_obj):    # for r_uint
     return constpropagate(pypy.rpython.rarithmetic.r_ulonglong, [s_obj],
-                          SomeInteger(size=2, nonneg=True, unsigned=True))
+                          SomeInteger(knowntype=pypy.rpython.rarithmetic.r_ulonglong))
 
 def restricted_base_int(s_obj):
     # insane hack: only for isinstance(., base_int), not for base_int()

Modified: pypy/dist/pypy/annotation/model.py
==============================================================================
--- pypy/dist/pypy/annotation/model.py	(original)
+++ pypy/dist/pypy/annotation/model.py	Wed May 10 14:22:20 2006
@@ -147,34 +147,27 @@
     "Stands for an object which is known to be an integer."
     knowntype = int
     # size is in multiples of C's sizeof(long)!
-    def __init__(self, nonneg=False, unsigned=False, size=1):
-        self.nonneg = unsigned or nonneg
-        self.unsigned = unsigned  # pypy.rpython.rarithmetic.r_uint
+    def __init__(self, nonneg=False, unsigned=None, knowntype=None):
+        
         if maxint != 2**31-1:
             size = 1    #XXX don't support longlong on 64 bits systems
-        self.size = size
-        if self.unsigned:
-            if self.size == 2:
-                self.knowntype = r_ulonglong
-            else:
-                self.knowntype = r_uint
-        else:
-            if self.size == 2:
-                self.knowntype = r_longlong
+        if knowntype is None:
+            if unsigned:
+                knowntype = r_uint
             else:
-                self.knowntype = int
-
-    def fmt_size(self, s):
-        if s != 1:
-            return str(s)
-
+                knowntype = int
+        elif unsigned is not None:
+            raise TypeError('Conflicting specification for SomeInteger')
+        self.knowntype = knowntype
+        unsigned = self.knowntype(-1) > 0
+        self.nonneg = unsigned or nonneg
+        self.unsigned = unsigned  # pypy.rpython.rarithmetic.r_uint
 
 class SomeBool(SomeInteger):
     "Stands for true or false."
     knowntype = bool
     nonneg = True
     unsigned = False
-    size = 1
     def __init__(self):
         pass
 
@@ -527,9 +520,9 @@
     (s_None, lltype.Void),   # also matches SomeImpossibleValue()
     (SomeBool(), lltype.Bool),
     (SomeInteger(), lltype.Signed),
-    (SomeInteger(size=2), lltype.SignedLongLong),    
-    (SomeInteger(nonneg=True, unsigned=True), lltype.Unsigned),    
-    (SomeInteger(nonneg=True, unsigned=True, size=2), lltype.UnsignedLongLong),    
+    (SomeInteger(knowntype=r_longlong), lltype.SignedLongLong),    
+    (SomeInteger(unsigned=True), lltype.Unsigned),    
+    (SomeInteger(knowntype=r_ulonglong), lltype.UnsignedLongLong),    
     (SomeFloat(), lltype.Float),
     (SomeChar(), lltype.Char),
     (SomeUnicodeCodePoint(), lltype.UniChar),

Modified: pypy/dist/pypy/annotation/unaryop.py
==============================================================================
--- pypy/dist/pypy/annotation/unaryop.py	(original)
+++ pypy/dist/pypy/annotation/unaryop.py	Wed May 10 14:22:20 2006
@@ -198,9 +198,7 @@
 class __extend__(SomeInteger):
 
     def invert(self):
-        if self.unsigned:
-            return SomeInteger(unsigned=True, size=self.size)
-        return SomeInteger(size=self.size)
+        return SomeInteger(knowntype=self.knowntype)
 
     invert.can_only_throw = []
 
@@ -213,17 +211,13 @@
     # these are the only ones which can overflow:
 
     def neg(self):
-        if self.unsigned:
-            return SomeInteger(unsigned=True, size=self.size)
-        return SomeInteger(size=self.size)
+        return SomeInteger(knowntype=self.knowntype)
 
     neg.can_only_throw = []
     neg_ovf = _clone(neg, [OverflowError])
 
     def abs(self):
-        if self.unsigned:
-            return self
-        return SomeInteger(nonneg=True, size=self.size)
+        return SomeInteger(nonneg=True, knowntype=self.knowntype)
 
     abs.can_only_throw = []
     abs_ovf = _clone(abs, [OverflowError])

Modified: pypy/dist/pypy/rpython/rarithmetic.py
==============================================================================
--- pypy/dist/pypy/rpython/rarithmetic.py	(original)
+++ pypy/dist/pypy/rpython/rarithmetic.py	Wed May 10 14:22:20 2006
@@ -84,15 +84,11 @@
     raise OverflowError
 
 def compute_restype(self_type, other_type):
-    if other_type in (int, long):
+    if other_type in (bool, int, long):
         return self_type
-    if self_type.SIGNED != other_type.SIGNED:
-        raise TypeError('Can not mix %r and %r'%(self_type, other_type))
-    if self_type.BITS > other_type.BITS:
-        return self_type
-    if self_type.BITS < other_type.BITS:
+    if self_type in (bool, int, long):
         return other_type
-    return self_type
+    return build_int(None, self_type.SIGNED and other_type.SIGNED, max(self_type.BITS, other_type.BITS))
 
 
 class base_int(long):
@@ -107,7 +103,7 @@
         self_type = type(self)
         other_type = type(other)
         try:
-            return self.typemap[ self_type, other_type ](value)
+            return self.typemap[self_type, other_type](value)
         except KeyError:
             pass
         restype = compute_restype(self_type, other_type)
@@ -274,6 +270,8 @@
     else:
         int_type = unsigned_int
     mask = (1 << bits) - 1
+    if name is None:
+        raise TypeError('No predefined %sint%d'%(['u', ''][sign], bits))
     ret = _inttypes[sign, bits] = type(name, (int_type,), {'MASK': mask,
                                                            'BITS': bits})
     return ret

Modified: pypy/dist/pypy/rpython/rctypes/test/test_rcarithmetic.py
==============================================================================
--- pypy/dist/pypy/rpython/rctypes/test/test_rcarithmetic.py	(original)
+++ pypy/dist/pypy/rpython/rctypes/test/test_rcarithmetic.py	Wed May 10 14:22:20 2006
@@ -14,8 +14,8 @@
     assert type(rcbyte(1) + rcshort(1)) is rcshort
     assert type(rcshort(1) + rcbyte(1)) is rcshort
 
-    py.test.raises(TypeError, 'rcubyte(1) + rcshort(1)')
-    py.test.raises(TypeError, 'rcshort(1) + rcubyte(1)')
+    assert type(rcubyte(1) + rcshort(1)) is rcushort
+    assert type(rcshort(1) + rcubyte(1)) is rcushort
 
     
 def test_typeof():

Modified: pypy/dist/pypy/rpython/rint.py
==============================================================================
--- pypy/dist/pypy/rpython/rint.py	(original)
+++ pypy/dist/pypy/rpython/rint.py	Wed May 10 14:22:20 2006
@@ -12,23 +12,22 @@
 from pypy.rpython.rmodel import log
 from pypy.rpython import objectmodel
 
-
 class __extend__(annmodel.SomeInteger):
     def rtyper_makerepr(self, rtyper):
-        if self.unsigned:
-            if self.size == 2:
-                return unsignedlonglong_repr
-            else:
-                assert self.size == 1
-                return unsigned_repr
-        else:
-            if self.size == 2:
-                return signedlonglong_repr
-            else:
-                assert self.size == 1
-                return signed_repr
+        if self.knowntype is int:
+            return signed_repr
+        if self.knowntype is bool:
+            return signed_repr
+        if self.knowntype is r_uint:
+            return unsigned_repr
+        if self.knowntype is r_longlong:
+            return signedlonglong_repr
+        if self.knowntype is r_ulonglong:
+            return unsignedlonglong_repr
+        raise TypeError('Can not build a repr for %r'%(self.knowntype,))
+
     def rtyper_makekey(self):
-        return self.__class__, self.unsigned, self.size
+        return self.__class__, self.knowntype
 
 signed_repr = IntegerRepr(Signed, 'int_')
 signedlonglong_repr = IntegerRepr(SignedLongLong, 'llong_')

Modified: pypy/dist/pypy/translator/stackless/transform.py
==============================================================================
--- pypy/dist/pypy/translator/stackless/transform.py	(original)
+++ pypy/dist/pypy/translator/stackless/transform.py	Wed May 10 14:22:20 2006
@@ -126,7 +126,7 @@
             lltype.Signed: mixlevelannotator.constfunc(
                 code.fetch_retval_long, [], annmodel.SomeInteger()),
             lltype.SignedLongLong: mixlevelannotator.constfunc(
-                code.fetch_retval_longlong, [], annmodel.SomeInteger(size=2)),
+                code.fetch_retval_longlong, [], annmodel.SomeInteger(knowntype=rarithmetic.r_longlong)),
             lltype.Float: mixlevelannotator.constfunc(
                 code.fetch_retval_float, [], annmodel.SomeFloat()),
             llmemory.Address: mixlevelannotator.constfunc(


From ale at codespeak.net  Wed May 10 17:49:48 2006
From: ale at codespeak.net (ale at codespeak.net)
Date: Wed, 10 May 2006 17:49:48 +0200 (CEST)
Subject: [pypy-svn] r27050 - in pypy/dist/pypy/lib/pyontology: . test
Message-ID: <20060510154948.1A1131008D@code0.codespeak.net>

Author: ale
Date: Wed May 10 17:49:46 2006
New Revision: 27050

Modified:
   pypy/dist/pypy/lib/pyontology/pyontology.py
   pypy/dist/pypy/lib/pyontology/test/test_ontology.py
Log:
Changes to allValuesFrom, someValuesFrom and bugfixes

Modified: pypy/dist/pypy/lib/pyontology/pyontology.py
==============================================================================
--- pypy/dist/pypy/lib/pyontology/pyontology.py	(original)
+++ pypy/dist/pypy/lib/pyontology/pyontology.py	Wed May 10 17:49:46 2006
@@ -89,7 +89,7 @@
         return self.bases
 
     def addValue(self, value):
-	    self.values[value] = True
+        self.values[value] = True
 
     def getValues(self):
         return self.values.keys()
@@ -116,7 +116,16 @@
     
     def getValues(self):
         items = self._dict.items()
-        return items
+        res = []
+        for k,vals in items:
+            for v in vals:
+                res.append((k,v))
+        return res
+
+    def getValuesPrKey(self, key= None):
+        if key:
+            return self._dict[key]
+        return self._dict.items()
     
     def addValue(self, key, val):
         self._dict.setdefault(key, [])
@@ -124,7 +133,6 @@
     
     def setValues(self, values):
         for key, val in values:
-            print val
             self.addValue(key, val)
     
     def removeValues(self, values):
@@ -175,7 +183,7 @@
     def addValue(self, key, val):
         Property.addValue(self, key, val)
         if len(self._dict[key]) > 1:
-	        raise ConsistencyFailure("FunctionalProperties can only have one value")
+            raise ConsistencyFailure("FunctionalProperties can only have one value")
         
 class InverseFunctionalProperty(Property):
     
@@ -270,7 +278,9 @@
 
     def add_file(self, f, format=None):
         tmp = Graph('default')
-        tmp.load(f, format)
+        if not format:
+            format = check_format(f)
+        tmp.load(f, format=format)
         for triple in tmp.triples((None,)*3):
             self.add(triple)
             
@@ -311,6 +321,11 @@
         for triple in item_as_subject:
             self.consider_triple(triple)
 
+    def resolve_predicate(self, item):
+        item_as_predicate = self.graph.triples(( None, item, None))
+        for triple in item_as_predicate:
+            self.consider_triple(triple)
+
     def get_individuals_of(self, item):
         item_as_subject = self.graph.triples(( None, rdf_type, item))
         for triple in item_as_subject:
@@ -325,6 +340,7 @@
             if ns not in uris.keys():
                 uris[ns] = ns.split('/')[-1]
             a = uris[ns] + '_' + name
+            var = str(a.replace('.','_'))
             var = str(a.replace('-','_'))
         else:
             var = a
@@ -361,7 +377,7 @@
     def check_TBoxes(self):
         for var, cls in self.variables.items():
             for prop, terms in cls.TBox.items():
-                if len(terms['Cardinality']) > 1: 
+                if len(terms.get('Cardinality',[])) > 1: 
                     self.evaluate(terms['Cardinality'])
     
     def solve(self,verbose=0):
@@ -426,6 +442,7 @@
         pass
     
     def onProperty(self, s, var):
+        self.resolve_predicate(var)
         svar =self.make_var(Restriction, s)
         avar =self.make_var(Property, var)
         restr = self.variables[svar]
@@ -454,12 +471,14 @@
                     prop.setdefault(typ, [])
                     prop[typ].extend(obj.TBox[key][typ])
 
-#            if isinstance(self.variables[avar], Restriction):
-#                self.variables.pop(avar)
+            if isinstance(self.variables[avar], Restriction):
+                self.variables[avar].TBox = {}
+                self.variables.pop(avar)
         else:
             cons = SubClassConstraint( svar, avar)
             self.constraints.append(cons)
-        self.get_individuals_of(var)
+        for item in obj.getValues():
+            sub.addValue(item)
 
     def equivalentClass(self, s, var):
         self.subClassOf(s, var)
@@ -529,9 +548,11 @@
         # s is a subproperty of var
         avar = self.make_var(Property, var)
         svar = self.make_var(Property, s)
-        cons = SubPropertyConstraint( svar, avar)
-        self.constraints.append(cons)
-    
+        avals = self.variables[avar].getValues()
+        for pair in self.variables[svar].getValues():
+            if not pair in avals:
+                self.variables[avar].addValue(pair[0], pair[1])
+
     def equivalentProperty(self, s, var):
         avar = self.make_var(Property, var)
         svar = self.make_var(Property, s)
@@ -539,10 +560,21 @@
         self.constraints.append(cons)
     
     def inverseOf(self, s, var):
+        self.resolve_item(s)
+        self.resolve_item(var)
         avar = self.make_var(Property, var)
         svar = self.make_var(Property, s)
-        con = InverseofConstraint(svar, avar)
-        self.constraints.append(con)
+#        con = InverseofConstraint(svar, avar)
+#        self.constraints.append(con)
+        avals = self.variables[avar].getValues()
+        svals = self.variables[svar].getValues()
+        #import pdb;pdb.set_trace()
+        for pair in avals:
+            if not (pair[1], pair[0]) in svals:
+	            self.variables[svar].addValue(pair[1], pair[0])
+        for pair in svals:
+            if not (pair[1], pair[0]) in avals:
+	            self.variables[avar].addValue(pair[1], pair[0])
 
 #---Property restrictions------------------------------------------------------
     
@@ -554,9 +586,13 @@
         cls_name = self.make_var(ClassDomain, cls)
         prop = self.variables[svar].property
         self.variables[svar].TBox[prop] = {'Cardinality': [( '<', int(var))]}
-        formula = "not isinstance(%s[0], self.variables[%s]) or len(%s[1] < int(%s))" %(prop, cls_name, prop, var)
-        constrain = Expression([prop], formula)
-        self.constraints.append(constrain)
+#        formula = "not isinstance(%s[0], self.variables[%s]) or len(%s[1] < int(%s))" %(prop, cls_name, prop, var)
+#        constrain = Expression([prop], formula)
+#        self.constraints.append(constrain)
+
+        for cls,vals in self.variables[prop].getValuesPrKey():
+            if len(vals) < int(var):
+                self.variables[svar].addValue(cls)
 
     def minCardinality(self, s, var):
         """ Len of finite domain of the property shall be greater than or equal to var"""
@@ -566,9 +602,10 @@
         cls_name = self.make_var(ClassDomain, cls)
         prop = self.variables[svar].property
         self.variables[svar].TBox[prop] = {'Cardinality': [( '>', int(var))]}
-        formula = "not isinstance(%s[0], self.variables[%s]) or len(%s[1] > int(%s))" %(prop, cls_name, prop, var)
-        constrain = Expression([prop], formula)
-        self.constraints.append(constrain)
+        for cls,vals in self.variables[prop].getValuesPrKey():
+            if len(vals) > int(var):
+                self.variables[svar].addValue(cls)
+
     
     def cardinality(self, s, var):
         """ Len of finite domain of the property shall be equal to var"""
@@ -578,9 +615,10 @@
         cls_name = self.make_var(ClassDomain, cls)
         prop = self.variables[svar].property
         self.variables[svar].TBox[prop] = {'Cardinality': [( '=', int(var))]}
-        formula = "not isinstance(%s[0], self.variables[%s]) or len(%s[1] == int(%s))" %(prop, cls_name, prop, var)
-        constrain = Expression([prop], formula)
-        self.constraints.append(constrain)
+        for cls,vals in self.variables[prop].getValuesPrKey():
+            if len(vals) == int(var):
+                self.variables[svar].addValue(cls)
+
     
     def hasValue(self, s, var):
         self.resolve_item(s)
@@ -590,8 +628,9 @@
         prop = self.variables[svar].property
         restr = self.variables[svar]
         restr.TBox[prop] = {'hasValue' : [('hasvalue', var)]}
-#        constrain = HasvalueConstraint(svar, avar)
-#        self.constraints.append(constrain)
+        for cls,vals in self.variables[prop].getValuesPrKey():
+            if var in vals:
+                self.variables[svar].addValue(cls)
     
     def allValuesFrom(self, s, var):
         self.resolve_item(s)
@@ -600,9 +639,12 @@
         avar = self.make_var(None, var)
         prop = self.variables[svar].property
         restr = self.variables[svar]
-        restr.TBox[prop] = {'allValues' : [('allValues', var)]}
-#        constrain = AllValueConstraint(svar, avar)
-#        self.constraints.append(constrain)
+        restr.TBox[prop] = {'allValuesFrom' : [('allValuesFrom', avar)]}
+        obj = self.variables[avar]
+        constrain_vals = set(obj.getValues())
+        for cls,vals in self.variables[prop].getValuesPrKey():
+            if (set(vals) & constrain_vals) == constrain_vals:
+                self.variables[svar].addValue(cls)
     
     def someValuesFrom(self, s, var):
         self.resolve_item(s)
@@ -611,9 +653,12 @@
         avar = self.make_var(None, var)
         prop = self.variables[svar].property
         restr = self.variables[svar]
-        restr.TBox[prop] = {'someValues' : [('someValues', var)]}
-#        constrain = SomeValueConstraint(svar, avar)
-#        self.constraints.append(constrain)
+        obj = self.variables[avar]
+        constrain_vals = set(obj.getValues())
+        restr.TBox[prop] = {'someValuesFrom' : [('someValuesFrom', avar)]}
+        for cls,vals in self.variables[prop].getValuesPrKey():
+            if set(vals) & constrain_vals:
+                self.variables[svar].addValue(cls)
 
 # -----------------              ----------------
     
@@ -645,4 +690,3 @@
                self.differentFrom(v, other)
         constrain = AllDifferentConstraint(s_var, var_var)
         self.constraints.append(constrain)
-

Modified: pypy/dist/pypy/lib/pyontology/test/test_ontology.py
==============================================================================
--- pypy/dist/pypy/lib/pyontology/test/test_ontology.py	(original)
+++ pypy/dist/pypy/lib/pyontology/test/test_ontology.py	Wed May 10 17:49:46 2006
@@ -55,9 +55,9 @@
     O = Ontology()
     a = O.make_var(Property, 'a')
     O.variables[a].addValue('key', 42)
-    assert O.variables[a].getValues() == [('key', [42])]
+    assert O.variables[a].getValues() == [('key', 42)]
     O.variables[a].addValue('key', 43)
-    assert O.variables[a].getValues() == [('key', [42, 43])]
+    assert O.variables[a].getValues() == [('key', 42), ('key', 43)]
 
 def no_test_ClassDomain():
     a = ClassDomain()
@@ -200,9 +200,8 @@
     O.type(sub, obj)
     b = URIRef('b')
     O.type(b, obj)
-    O.subPropertyOf(sub, b)
-    assert len(O.constraints) ==1
     O.variables['a_'].setValues([('individ_',42)])
+    O.subPropertyOf(sub, b)
     O.consistency()
     for val in O.variables['a_'].getValues():
         assert  val in O.variables['b_'].getValues()
@@ -292,10 +291,10 @@
     O.type(sub, obj)
     O.variables['friend_'].setValues([('Bob_','Alice_')])
     O.consistency()
-    assert ('Alice_', ['Bob_']) in O.variables['friend_'].getValues()
+    assert ('Alice_', 'Bob_') in O.variables['friend_'].getValues()
 
 def test_inverseof():
-    py.test.skip("in transit")
+    #py.test.skip("in transit")
     O = Ontology()
     own = URIRef('owner')
     obj = URIRef(namespaces['owl']+'#ObjectProperty')
@@ -303,7 +302,6 @@
     owned = URIRef('ownedby')
     obj = URIRef(namespaces['owl']+'#ObjectProperty')
     O.type(owned, obj)
-    O.inverseOf(own, owned)
     #Make class
     sub = URIRef('c')
     obj = URIRef(namespaces['owl']+'#Class')
@@ -316,27 +314,29 @@
     obj = URIRef('car')
     O.type(sub, obj)
     O.variables['owner_'].setValues([('Bob_','Fiat_')])
-    py.test.raises(ConsistencyFailure, O.consistency)
-    O.variables['ownedby_'].setValues([('Fiat_','Bob_')])
-    O.consistency()
-    
+    O.inverseOf(own, owned)
+    assert ('Fiat_','Bob_') in O.variables['ownedby_'].getValues()   
 def test_hasvalue():
-    py.test.skip("in transit")
     O = Ontology()
+    cls = URIRef('class')
+    obj = URIRef(namespaces['owl']+'#Class')
+    O.type(cls, obj)
     restrict = BNode('anon1')
     obj = URIRef(namespaces['owl']+'#Restriction')
     O.type(restrict, obj)
     p = URIRef('p')
     obj = URIRef(namespaces['owl']+'#ObjectProperty')
     O.type(p, obj)
-    O.hasValue(restrict, 2)
+    O.consider_triple((cls, p, 2))
     O.onProperty(restrict,p)
-    cls = URIRef('class')
+    O.variables['p_'].setValues([(O.make_var(None,cls),1)])
+    O.hasValue(restrict, 2)
+    cls2 = URIRef('class2')
     obj = URIRef(namespaces['owl']+'#Class')
-    O.type(cls, obj)
-    O.subClassOf(cls,restrict)
-    O.variables['p_'].setValues([(cls,1)])
-    py.test.raises(ConsistencyFailure, O.consistency)
+    O.type(cls2, obj)
+    O.subClassOf(cls2,restrict)
+    assert O.make_var(None, cls) in O.variables[O.make_var(None, cls2)].getValues()
+#    py.test.raises(ConsistencyFailure, O.consistency)
 
 def test_List():
     py.test.skip("Need to be rewritten using RDF-XML")
@@ -351,7 +351,7 @@
     O.first( URIRef('2'), 2)
     O.rest( URIRef('2'),  URIRef(namespaces['rdf']+'#nil'))
     O.flatten_rdf_list(own)
-    O.consistency(5)
+    O.consistency()
     assert O.rep._domains['favlist_'].getValues() == [0,1,2]
 
 def test_oneofclassenumeration():
@@ -360,7 +360,7 @@
     own = [UR('first'), UR('second'), UR('third')]
     O.oneOf(restrict, own)
     O.type(restrict, namespaces['owl']+'#Class')
-    O.consistency(4)
+    O.consistency()
     assert len(O.rep._domains[restrict].getValues()) == 3
     assert set(O.rep._domains[restrict].getValues()) == set(own)
 
@@ -370,12 +370,12 @@
     own = ['1','2','3'] 
     O.oneOf(restrict, own)
     O.type(restrict, namespaces['owl']+'#DataRange')
-    O.consistency(4)
+    O.consistency()
     assert len(O.rep._domains[restrict].getValues()) == 3
     assert set(O.rep._domains[restrict].getValues()) == set(own)
 
 def test_somevaluesfrom_datarange():
-    py.test.skip("in flux")
+
     O = Ontology()
     datarange = BNode('anon')
     own =  ['1','2','3']
@@ -387,17 +387,16 @@
     p = URIRef('p')
     obj = URIRef(namespaces['owl']+'#ObjectProperty')
     O.type(p, obj)
-    O.someValuesFrom(restrict, datarange)
-    O.onProperty(restrict,p)
     cls = URIRef('class')
     obj = URIRef(namespaces['owl']+'#Class')
     O.type(cls, obj)
+    O.variables['p_'].setValues([(cls,'1')])
+    O.onProperty(restrict,p)
+    O.someValuesFrom(restrict, datarange)
     O.subClassOf(cls,restrict)
-    O.variables['p_'].setValues([(cls,1)])
-    py.test.raises(ConsistencyFailure, O.consistency)
+    assert cls in O.variables[O.make_var(None, cls)].getValues()
 
 def test_allvaluesfrom_datarange():
-    py.test.skip("in flux")
     O = Ontology()
     datarange = BNode('anon')
     own = ['1','2','3']
@@ -409,14 +408,14 @@
     p = URIRef('p')
     obj = URIRef(namespaces['owl']+'#ObjectProperty')
     O.type(p, obj)
-    O.allValuesFrom(restrict, datarange)
-    O.onProperty(restrict,p)
     cls = URIRef('class')
+    O.variables['p_'].setValues([(cls,'1'),(cls,'2'),(cls,'3')])
     obj = URIRef(namespaces['owl']+'#Class')
     O.type(cls, obj)
+    O.onProperty(restrict,p)
+    O.allValuesFrom(restrict, datarange)
     O.subClassOf(cls,restrict)
-    O.variables['p_'].setValues([(cls,1)])
-    py.test.raises(ConsistencyFailure, O.consistency)
+    assert cls in O.variables[O.make_var(None, cls)].getValues()
 
 def test_unionof():
     O = Ontology()
@@ -430,7 +429,7 @@
     O.oneOf( own2, list2)
     O.unionOf(cls, own)
     O.type(cls, namespaces['owl']+'#Class')
-    O.consistency(3)
+    O.consistency()
     res = O.rep._domains[cls].getValues()
     res.sort()
     assert res == ['1', '2', '3', '4', '5']
@@ -440,7 +439,7 @@
     cls = BNode('anon')
     O.intersectionOf(cls, [['1','2','3'],['3','4','5']])
     O.type(cls, namespaces['owl']+'#Class')
-    O.consistency(3)
+    O.consistency()
     assert O.rep._domains[cls].getValues() == ['3']
 
 def test_differentfrom():
@@ -455,7 +454,7 @@
     O.type(cls, namespaces['owl']+'#Thing')
     O.type(own1, namespaces['owl']+'#Thing')
     O.type(own2, namespaces['owl']+'#Thing')
-    O.consistency(3)
+    O.consistency()
     assert len(O.rep._constraints) == 4
 
 def test_differentfromconsistency():
@@ -463,7 +462,7 @@
     cls = BNode('anon')
     O.differentFrom(cls, cls)
     O.type(cls, namespaces['owl']+'#Thing')
-    py.test.raises(ConsistencyFailure, O.consistency, 3)
+    py.test.raises(ConsistencyFailure, O.consistency)
 
 def test_sameas():
     O = Ontology()
@@ -480,8 +479,8 @@
     obj = URIRef(namespaces['owl']+'#ObjectProperty')
     O.type(sub, obj)
     O.variables[O.make_var(None,sub)].setValues([(cls,'1')])
-    O.consistency(3)
-    assert ('liist1',['1']) in O.rep._domains[O.make_var(None,sub)].getValues()
+    O.consistency()
+    assert ('liist1','1') in O.rep._domains[O.make_var(None,sub)].getValues()
 
 def test_sameasconsistency():
     O = Ontology()
@@ -494,7 +493,7 @@
     obj = URIRef(namespaces['owl']+'#ObjectProperty')
     O.type(sub, obj)
     O.variables[O.make_var(None,sub)].setValues([(cls,'1'), (own1,'2')])
-    py.test.raises(ConsistencyFailure, O.consistency, 3)
+    py.test.raises(ConsistencyFailure, O.consistency)
 
 
 def test_cardinality_terminology():


From ac at codespeak.net  Wed May 10 19:54:38 2006
From: ac at codespeak.net (ac at codespeak.net)
Date: Wed, 10 May 2006 19:54:38 +0200 (CEST)
Subject: [pypy-svn] r27051 - in pypy/dist/pypy: annotation annotation/test
	rpython rpython/lltypesystem rpython/rctypes
	rpython/rctypes/test rpython/test
Message-ID: <20060510175438.4366B10089@code0.codespeak.net>

Author: ac
Date: Wed May 10 19:54:37 2006
New Revision: 27051

Modified:
   pypy/dist/pypy/annotation/binaryop.py
   pypy/dist/pypy/annotation/bookkeeper.py
   pypy/dist/pypy/annotation/builtin.py
   pypy/dist/pypy/annotation/model.py
   pypy/dist/pypy/annotation/test/test_annrpython.py
   pypy/dist/pypy/annotation/unaryop.py
   pypy/dist/pypy/rpython/lltypesystem/lltype.py
   pypy/dist/pypy/rpython/rarithmetic.py
   pypy/dist/pypy/rpython/rbuiltin.py
   pypy/dist/pypy/rpython/rctypes/rprimitive.py
   pypy/dist/pypy/rpython/rctypes/test/test_rcarithmetic.py
   pypy/dist/pypy/rpython/rint.py
   pypy/dist/pypy/rpython/rmodel.py
   pypy/dist/pypy/rpython/rtyper.py
   pypy/dist/pypy/rpython/test/test_rint.py
Log:
(pedronis, arre)
Support annotating and rtyping of arbitrary sized integers. No operations
supported yet apart adding lltype.cast_primitive support.



Modified: pypy/dist/pypy/annotation/binaryop.py
==============================================================================
--- pypy/dist/pypy/annotation/binaryop.py	(original)
+++ pypy/dist/pypy/annotation/binaryop.py	Wed May 10 19:54:37 2006
@@ -296,6 +296,14 @@
     def gt(intint): return intint._compare_helper('gt', operator.gt)
     def ge(intint): return intint._compare_helper('ge', operator.ge)
 
+class __extend__(pairtype(SomeBool, SomeInteger)):
+    def lshift((int1, int2)):
+        return SomeInteger()
+
+    lshift.can_only_throw = [ValueError]
+    rshift = lshift
+    lshift_ovf = _clone(lshift, [ValueError, OverflowError])
+
 
 class __extend__(pairtype(SomeBool, SomeBool)):
 

Modified: pypy/dist/pypy/annotation/bookkeeper.py
==============================================================================
--- pypy/dist/pypy/annotation/bookkeeper.py	(original)
+++ pypy/dist/pypy/annotation/bookkeeper.py	Wed May 10 19:54:37 2006
@@ -310,14 +310,8 @@
             return x.annotation()
         if tp is bool:
             result = SomeBool()
-        elif tp is int or tp is r_int:
+        elif tp is int:
             result = SomeInteger(nonneg = x>=0)
-        elif tp is r_uint:
-            result = SomeInteger(nonneg = True, unsigned = True)
-        elif tp is r_ulonglong:
-            result = SomeInteger(nonneg = True, knowntype=r_ulonglong)
-        elif tp is r_longlong:
-            result = SomeInteger(nonneg = x>=0, knowntype=r_longlong)
         elif issubclass(tp, str): # py.lib uses annotated str subclasses
             if len(x) == 1:
                 result = SomeChar()
@@ -500,14 +494,8 @@
         assert isinstance(t, (type, types.ClassType))
         if t is bool:
             return SomeBool()
-        elif t is int or t is r_int:
+        elif t is int:
             return SomeInteger()
-        elif t is r_uint:
-            return SomeInteger(unsigned = True)
-        elif t is r_ulonglong or t is base_int:
-            return SomeInteger(knowntype=r_ulonglong)
-        elif t is r_longlong:
-            return SomeInteger(knowntype=r_longlong)
         elif issubclass(t, str): # py.lib uses annotated str subclasses
             return SomeString()
         elif t is float:

Modified: pypy/dist/pypy/annotation/builtin.py
==============================================================================
--- pypy/dist/pypy/annotation/builtin.py	(original)
+++ pypy/dist/pypy/annotation/builtin.py	Wed May 10 19:54:37 2006
@@ -81,22 +81,6 @@
         args_s = [s_obj]
     return constpropagate(int, args_s, SomeInteger())
 
-def restricted_uint(s_obj):    # for r_uint
-    return constpropagate(pypy.rpython.rarithmetic.r_uint, [s_obj],
-                          SomeInteger(nonneg=True, unsigned=True))
-
-def restricted_longlong(s_obj):    # for r_uint
-    return constpropagate(pypy.rpython.rarithmetic.r_longlong, [s_obj],
-                          SomeInteger(knowntype=pypy.rpython.rarithmetic.r_longlong))
-
-def restricted_ulonglong(s_obj):    # for r_uint
-    return constpropagate(pypy.rpython.rarithmetic.r_ulonglong, [s_obj],
-                          SomeInteger(knowntype=pypy.rpython.rarithmetic.r_ulonglong))
-
-def restricted_base_int(s_obj):
-    # insane hack: only for isinstance(., base_int), not for base_int()
-    raise Exception("cannot call rarithmetic.base_int()")
-
 def builtin_float(s_obj):
     return constpropagate(float, [s_obj], SomeFloat())
 
@@ -356,10 +340,6 @@
         original = getattr(__builtin__, name[8:])
         BUILTIN_ANALYZERS[original] = value
 
-BUILTIN_ANALYZERS[pypy.rpython.rarithmetic.r_uint] = restricted_uint
-BUILTIN_ANALYZERS[pypy.rpython.rarithmetic.r_longlong] = restricted_longlong
-BUILTIN_ANALYZERS[pypy.rpython.rarithmetic.r_ulonglong] = restricted_ulonglong
-BUILTIN_ANALYZERS[pypy.rpython.rarithmetic.base_int] = restricted_base_int
 ##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

Modified: pypy/dist/pypy/annotation/model.py
==============================================================================
--- pypy/dist/pypy/annotation/model.py	(original)
+++ pypy/dist/pypy/annotation/model.py	Wed May 10 19:54:37 2006
@@ -32,7 +32,7 @@
 import pypy.tool.instancemethod
 from pypy.annotation.pairtype import pair, extendabletype
 from pypy.tool.tls import tlsobject
-from pypy.rpython.rarithmetic import r_uint, r_longlong, r_ulonglong
+from pypy.rpython.rarithmetic import r_uint, r_longlong, r_ulonglong, base_int
 import inspect
 from sys import maxint
 
@@ -148,9 +148,8 @@
     knowntype = int
     # size is in multiples of C's sizeof(long)!
     def __init__(self, nonneg=False, unsigned=None, knowntype=None):
-        
-        if maxint != 2**31-1:
-            size = 1    #XXX don't support longlong on 64 bits systems
+        assert (knowntype is None or knowntype is int or
+                issubclass(knowntype, base_int))
         if knowntype is None:
             if unsigned:
                 knowntype = r_uint
@@ -516,13 +515,11 @@
 from pypy.rpython.lltypesystem import lltype
 from pypy.rpython.ootypesystem import ootype
 
+NUMBER = object()
 annotation_to_ll_map = [
     (s_None, lltype.Void),   # also matches SomeImpossibleValue()
     (SomeBool(), lltype.Bool),
-    (SomeInteger(), lltype.Signed),
-    (SomeInteger(knowntype=r_longlong), lltype.SignedLongLong),    
-    (SomeInteger(unsigned=True), lltype.Unsigned),    
-    (SomeInteger(knowntype=r_ulonglong), lltype.UnsignedLongLong),    
+    (SomeInteger(knowntype=r_ulonglong), NUMBER),    
     (SomeFloat(), lltype.Float),
     (SomeChar(), lltype.Char),
     (SomeUnicodeCodePoint(), lltype.UniChar),
@@ -536,9 +533,11 @@
         return s_val.method
     if isinstance(s_val, SomePtr):
         return s_val.ll_ptrtype
-    for witness, lltype in annotation_to_ll_map:
+    for witness, T in annotation_to_ll_map:
         if witness.contains(s_val):
-            return lltype
+            if T is NUMBER:
+                return lltype.build_number(None, s_val.knowntype)
+            return T
     if info is None:
         info = ''
     else:
@@ -546,7 +545,7 @@
     raise ValueError("%sshould return a low-level type,\ngot instead %r" % (
         info, s_val))
 
-ll_to_annotation_map = dict([(ll, ann) for ann, ll in annotation_to_ll_map])
+ll_to_annotation_map = dict([(ll, ann) for ann, ll in annotation_to_ll_map if ll is not NUMBER])
 
 def lltype_to_annotation(T):
     try:
@@ -554,6 +553,8 @@
     except TypeError:
         s = None    # unhashable T, e.g. a Ptr(GcForwardReference())
     if s is None:
+        if isinstance(T, lltype.Number):
+            return SomeInteger(knowntype=T._type)
         if isinstance(T, (ootype.Instance, ootype.BuiltinType)):
             return SomeOOInstance(T)
         elif isinstance(T, ootype.StaticMethod):

Modified: pypy/dist/pypy/annotation/test/test_annrpython.py
==============================================================================
--- pypy/dist/pypy/annotation/test/test_annrpython.py	(original)
+++ pypy/dist/pypy/annotation/test/test_annrpython.py	Wed May 10 19:54:37 2006
@@ -10,7 +10,7 @@
 from pypy.annotation.listdef import ListDef
 from pypy.annotation.dictdef import DictDef
 from pypy.objspace.flow.model import *
-from pypy.rpython.rarithmetic import r_uint, base_int
+from pypy.rpython.rarithmetic import r_uint, base_int, r_longlong, r_ulonglong
 from pypy.rpython import objectmodel
 from pypy.objspace.flow import FlowObjSpace
 
@@ -2087,6 +2087,83 @@
         assert s.knowntype == int
 
 
+    def test_annotate_bool(self):
+        def f(x):
+            return ~x
+        a = self.RPythonAnnotator()
+        s = a.build_types(f, [bool])
+        assert s.knowntype == int
+        
+
+        def f(x):
+            return -x
+        a = self.RPythonAnnotator()
+        s = a.build_types(f, [bool])
+        assert s.knowntype == int
+
+        def f(x):
+            return +x
+        a = self.RPythonAnnotator()
+        s = a.build_types(f, [bool])
+        assert s.knowntype == int
+
+        def f(x):
+            return abs(x)
+        a = self.RPythonAnnotator()
+        s = a.build_types(f, [bool])
+        assert s.knowntype == int
+
+        def f(x):
+            return int(x)
+        a = self.RPythonAnnotator()
+        s = a.build_types(f, [bool])
+        assert s.knowntype == int
+
+
+        def f(x, y):
+            return x + y
+        a = self.RPythonAnnotator()
+        s = a.build_types(f, [bool, int])
+        assert s.knowntype == int
+
+        a = self.RPythonAnnotator()
+        s = a.build_types(f, [int, bool])
+        assert s.knowntype == int
+
+
+
+    def test_annotate_rarith(self):
+        inttypes = [int, r_uint, r_longlong, r_ulonglong]
+        for inttype in inttypes:
+            c = inttype()
+            def f():
+                return c
+            a = self.RPythonAnnotator()
+            s = a.build_types(f, [])
+            assert isinstance(s, annmodel.SomeInteger)
+            assert s.knowntype == inttype
+            assert s.unsigned == (inttype(-1) > 0)
+            
+        for inttype in inttypes:
+            def f():
+                return inttype(0)
+            a = self.RPythonAnnotator()
+            s = a.build_types(f, [])
+            assert isinstance(s, annmodel.SomeInteger)
+            assert s.knowntype == inttype
+            assert s.unsigned == (inttype(-1) > 0)
+
+        for inttype in inttypes:
+            def f(x):
+                return x
+            a = self.RPythonAnnotator()
+            s = a.build_types(f, [inttype])
+            assert isinstance(s, annmodel.SomeInteger)
+            assert s.knowntype == inttype
+            assert s.unsigned == (inttype(-1) > 0)
+        
+
+
 def g(n):
     return [0,1,2,n]
 

Modified: pypy/dist/pypy/annotation/unaryop.py
==============================================================================
--- pypy/dist/pypy/annotation/unaryop.py	(original)
+++ pypy/dist/pypy/annotation/unaryop.py	Wed May 10 19:54:37 2006
@@ -203,7 +203,7 @@
     invert.can_only_throw = []
 
     def pos(self):
-        return self
+        return SomeInteger(knowntype=self.knowntype)
 
     pos.can_only_throw = []
     int = pos
@@ -226,6 +226,28 @@
     def is_true(self):
         return self
 
+    def invert(self):
+        return SomeInteger()
+
+    invert.can_only_throw = []
+
+    def neg(self):
+        return SomeInteger()
+
+    neg.can_only_throw = []
+    neg_ovf = _clone(neg, [OverflowError])
+
+    def abs(self):
+        return SomeInteger(nonneg=True)
+
+    abs.can_only_throw = []
+    abs_ovf = _clone(abs, [OverflowError])
+
+    def pos(self):
+        return SomeInteger(nonneg=True)
+
+    pos.can_only_throw = []
+    int = pos
 
 class __extend__(SomeTuple):
 

Modified: pypy/dist/pypy/rpython/lltypesystem/lltype.py
==============================================================================
--- pypy/dist/pypy/rpython/lltypesystem/lltype.py	(original)
+++ pypy/dist/pypy/rpython/lltypesystem/lltype.py	Wed May 10 19:54:37 2006
@@ -1,5 +1,6 @@
 import py
-from pypy.rpython.rarithmetic import r_int, r_uint, r_ulonglong, r_longlong, base_int
+from pypy.rpython.rarithmetic import r_int, r_uint, intmask
+from pypy.rpython.rarithmetic import r_ulonglong, r_longlong, base_int
 from pypy.rpython.objectmodel import Symbolic
 from pypy.tool.uid import Hashable
 from pypy.tool.tls import tlsobject
@@ -480,7 +481,17 @@
 
     _example = _defl
 
-_numbertypes = {int: Primitive("Signed", 0)}
+class Number(Primitive):
+
+    def __init__(self, name, type, cast=None):
+        Primitive.__init__(self, name, type())
+        self._type = type
+        if cast is None:
+            self._cast = type
+        else:
+            self._cast = cast
+
+_numbertypes = {int: Number("Signed", int, )}
 _numbertypes[r_int] = _numbertypes[int]
 
 def build_number(name, type):
@@ -490,15 +501,15 @@
         pass
     if name is None:
         raise ValueError('No matching lowlevel type for %r'%type)
-    number = _numbertypes[type] = Primitive(name, type())
+    number = _numbertypes[type] = Number(name, type)
     return number
 
 Signed   = build_number("Signed", int)
 Unsigned = build_number("Unsigned", r_uint)
 SignedLongLong = build_number("SignedLongLong", r_longlong)
 UnsignedLongLong = build_number("UnsignedLongLong", r_ulonglong)
-Float    = build_number("Float", float)
 
+Float    = Primitive("Float", 0.0)
 Char     = Primitive("Char", '\x00')
 Bool     = Primitive("Bool", False)
 Void     = Primitive("Void", None)
@@ -563,11 +574,9 @@
         raise TypeError("typeOf(%r object)" % (tp.__name__,))
 
 _to_primitive = {
-    Signed: int,
-    Unsigned: r_uint,
-    Float: float,
     Char: chr,
     UniChar: unichr,
+    Float: float,
     Bool: bool,
 }
 
@@ -582,9 +591,11 @@
     elif ORIG == Float:
         value = long(value)
     cast = _to_primitive.get(TGT)
-    if cast is None:
-        raise TypeError, "unsupported cast"
-    return cast(value)
+    if cast is not None:
+        return cast(value)
+    if isinstance(TGT, Number):
+        return TGT._cast(value)
+    raise TypeError, "unsupported cast"
 
 def _cast_whatever(TGT, value):
     from pypy.rpython.lltypesystem import llmemory

Modified: pypy/dist/pypy/rpython/rarithmetic.py
==============================================================================
--- pypy/dist/pypy/rpython/rarithmetic.py	(original)
+++ pypy/dist/pypy/rpython/rarithmetic.py	Wed May 10 19:54:37 2006
@@ -29,6 +29,7 @@
 
 """
 import math
+from pypy.rpython import extregistry
 
 # set up of machine internals
 _bits = 0
@@ -85,6 +86,8 @@
 
 def compute_restype(self_type, other_type):
     if other_type in (bool, int, long):
+        if self_type is bool:
+            return int
         return self_type
     if self_type in (bool, int, long):
         return other_type
@@ -266,15 +269,46 @@
     except KeyError:
         pass
     if sign:
-        int_type = signed_int
+        base_int_type = signed_int
     else:
-        int_type = unsigned_int
+        base_int_type = unsigned_int
     mask = (1 << bits) - 1
     if name is None:
         raise TypeError('No predefined %sint%d'%(['u', ''][sign], bits))
-    ret = _inttypes[sign, bits] = type(name, (int_type,), {'MASK': mask,
+    int_type = _inttypes[sign, bits] = type(name, (base_int_type,), {'MASK': mask,
                                                            'BITS': bits})
-    return ret
+    class ForValuesEntry(extregistry.ExtRegistryEntry):
+        _type_ = int_type
+
+        def compute_annotation(self):
+            from pypy.annotation import model as annmodel
+            return annmodel.SomeInteger(knowntype=int_type)
+            
+    class ForTypeEntry(extregistry.ExtRegistryEntry):
+        _about_ = int_type
+
+        def compute_result_annotation(self, *args_s, **kwds_s):
+            from pypy.annotation import model as annmodel
+            return annmodel.SomeInteger(knowntype=int_type)
+
+        def specialize_call(self, hop):
+            v_result, = hop.inputargs(hop.r_result.lowleveltype)
+            return v_result
+            
+    return int_type
+
+class BaseIntValueEntry(extregistry.ExtRegistryEntry):
+    _type_ = base_int
+
+    def compute_annotation(self):
+        from pypy.annotation import model as annmodel
+        return annmodel.SomeInteger(knowntype=r_ulonglong)
+        
+class BaseIntTypeEntry(extregistry.ExtRegistryEntry):
+    _about_ = base_int
+
+    def compute_result_annotation(self, *args_s, **kwds_s):
+        raise TypeError("abstract base!")
 
 r_int = build_int('r_int', True, LONG_BIT)
 r_uint = build_int('r_uint', False, LONG_BIT)

Modified: pypy/dist/pypy/rpython/rbuiltin.py
==============================================================================
--- pypy/dist/pypy/rpython/rbuiltin.py	(original)
+++ pypy/dist/pypy/rpython/rbuiltin.py	Wed May 10 19:54:37 2006
@@ -200,18 +200,6 @@
     vlist = hop.inputargs(lltype.Signed)
     return vlist[0]
 
-def rtype_r_uint(hop):
-    vlist = hop.inputargs(lltype.Unsigned)
-    return vlist[0]
-
-def rtype_r_longlong(hop):
-    vlist = hop.inputargs(lltype.SignedLongLong)
-    return vlist[0]
-
-def rtype_r_ulonglong(hop):
-    vlist = hop.inputargs(lltype.UnsignedLongLong)
-    return vlist[0]
-
 def rtype_builtin_min(hop):
     rint1, rint2 = hop.args_r
     assert isinstance(rint1, IntegerRepr)
@@ -446,9 +434,6 @@
 BUILTIN_TYPER[lltype.Ptr] = 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
-BUILTIN_TYPER[rarithmetic.r_longlong] = rtype_r_longlong
-BUILTIN_TYPER[rarithmetic.r_ulonglong] = rtype_r_ulonglong
 BUILTIN_TYPER[objectmodel.r_dict] = rtype_r_dict
 BUILTIN_TYPER[objectmodel.we_are_translated] = rtype_we_are_translated
 BUILTIN_TYPER[rstack.yield_current_frame_to_caller] = (

Modified: pypy/dist/pypy/rpython/rctypes/rprimitive.py
==============================================================================
--- pypy/dist/pypy/rpython/rctypes/rprimitive.py	(original)
+++ pypy/dist/pypy/rpython/rctypes/rprimitive.py	Wed May 10 19:54:37 2006
@@ -42,7 +42,7 @@
                  pairtype(UniCharRepr, PrimitiveRepr)):
     def convert_from_to((r_from, r_to), v, llops):
         # first convert 'v' to the precise expected low-level type
-        r_input = r_to.rtyper.primitive_to_repr[r_to.ll_type]
+        r_input = r_to.rtyper.getprimitiverepr(r_to.ll_type)
         v = llops.convertvar(v, r_from, r_input)
         # allocate a memory-owning box to hold a copy of the ll value 'v'
         r_temp = r_to.r_memoryowner

Modified: pypy/dist/pypy/rpython/rctypes/test/test_rcarithmetic.py
==============================================================================
--- pypy/dist/pypy/rpython/rctypes/test/test_rcarithmetic.py	(original)
+++ pypy/dist/pypy/rpython/rctypes/test/test_rcarithmetic.py	Wed May 10 19:54:37 2006
@@ -2,6 +2,17 @@
 from pypy.rpython.rctypes.rcarithmetic import *
 from pypy.rpython.lltypesystem import lltype
 from pypy.rpython import rarithmetic
+from pypy.annotation import model as annmodel
+from pypy.annotation.annrpython import RPythonAnnotator
+from pypy.rpython.test.test_llinterp import interpret
+from pypy.rpython.error import TyperError
+from pypy.translator.translator import TranslationContext
+
+def specialize(func, types):
+    t = TranslationContext()
+    t.buildannotator().build_types(func, types)
+    t.buildrtyper().specialize()
+    t.checkgraphs()    
 
 def test_signedness():
     assert rcbyte(-1) < 0
@@ -30,3 +41,66 @@
     assert lltype.typeOf(rcshort(0)) == CShort
 
     assert lltype.typeOf(rcushort(0)) == CUShort
+
+inttypes = [rcbyte, rcubyte, rcshort, rcushort, rcint, rcuint,
+            rclong, rculong, rclonglong, rculonglong]
+
+def test_annotate():
+    for inttype in inttypes:
+        c = inttype()
+        def f():
+            return c
+        a = RPythonAnnotator()
+        s = a.build_types(f, [])
+        assert isinstance(s, annmodel.SomeInteger)
+        assert s.knowntype == inttype
+        assert s.unsigned == (inttype(-1) > 0)
+
+    for inttype in inttypes:
+        def f():
+            return inttype(0)
+        a = RPythonAnnotator()
+        s = a.build_types(f, [])
+        assert isinstance(s, annmodel.SomeInteger)
+        assert s.knowntype == inttype
+        assert s.unsigned == (inttype(-1) > 0)
+
+    for inttype in inttypes:
+        def f(x):
+            return x
+        a = RPythonAnnotator()
+        s = a.build_types(f, [inttype])
+        assert isinstance(s, annmodel.SomeInteger)
+        assert s.knowntype == inttype
+        assert s.unsigned == (inttype(-1) > 0)
+
+def test_specialize():
+    for inttype in inttypes:
+        c = inttype()
+        def f():
+            return c
+        res = interpret(f, [])
+        assert res == f()
+        assert lltype.typeOf(res) == lltype.build_number(None, inttype)
+
+    for inttype in inttypes:
+        def f():
+            return inttype(0)
+        res = interpret(f, [])
+        assert res == f()
+        assert lltype.typeOf(res) == lltype.build_number(None, inttype)        
+
+    for inttype in inttypes:
+        def f(x):
+            return x
+        res = interpret(f, [inttype(0)])
+        assert res == f(inttype(0))
+        assert lltype.typeOf(res) == lltype.build_number(None, inttype)
+
+        
+def test_unsupported_op():
+    def f(x, y):
+        return x + y
+
+    py.test.raises(TyperError, specialize, f, [rcbyte, rcbyte])
+    

Modified: pypy/dist/pypy/rpython/rint.py
==============================================================================
--- pypy/dist/pypy/rpython/rint.py	(original)
+++ pypy/dist/pypy/rpython/rint.py	Wed May 10 19:54:37 2006
@@ -4,7 +4,8 @@
 from pypy.objspace.flow.objspace import op_appendices
 from pypy.rpython.lltypesystem.lltype import Signed, Unsigned, Bool, Float, \
      Void, Char, UniChar, GcArray, malloc, Array, pyobjectptr, \
-     UnsignedLongLong, SignedLongLong
+     UnsignedLongLong, SignedLongLong, build_number, Number, cast_primitive, \
+     typeOf
 from pypy.rpython.rmodel import IntegerRepr, inputconst
 from pypy.rpython.robject import PyObjRepr, pyobj_repr
 from pypy.rpython.rarithmetic import intmask, r_int, r_uint, r_ulonglong, r_longlong
@@ -12,27 +13,27 @@
 from pypy.rpython.rmodel import log
 from pypy.rpython import objectmodel
 
+_integer_reprs = {}
+def getintegerrepr(lltype, prefix=None):
+    try:
+        return _integer_reprs[lltype]
+    except KeyError:
+        pass
+    repr = _integer_reprs[lltype] = IntegerRepr(lltype, prefix)
+    return repr
+
 class __extend__(annmodel.SomeInteger):
     def rtyper_makerepr(self, rtyper):
-        if self.knowntype is int:
-            return signed_repr
-        if self.knowntype is bool:
-            return signed_repr
-        if self.knowntype is r_uint:
-            return unsigned_repr
-        if self.knowntype is r_longlong:
-            return signedlonglong_repr
-        if self.knowntype is r_ulonglong:
-            return unsignedlonglong_repr
-        raise TypeError('Can not build a repr for %r'%(self.knowntype,))
+        lltype = build_number(None, self.knowntype)
+        return getintegerrepr(lltype)
 
     def rtyper_makekey(self):
         return self.__class__, self.knowntype
 
-signed_repr = IntegerRepr(Signed, 'int_')
-signedlonglong_repr = IntegerRepr(SignedLongLong, 'llong_')
-unsigned_repr = IntegerRepr(Unsigned, 'uint_')
-unsignedlonglong_repr = IntegerRepr(UnsignedLongLong, 'ullong_')
+signed_repr = getintegerrepr(Signed, 'int_')
+signedlonglong_repr = getintegerrepr(SignedLongLong, 'llong_')
+unsigned_repr = getintegerrepr(Unsigned, 'uint_')
+unsignedlonglong_repr = getintegerrepr(UnsignedLongLong, 'ullong_')
 
 
 class __extend__(pairtype(IntegerRepr, IntegerRepr)):
@@ -201,17 +202,10 @@
     def convert_const(self, value):
         if isinstance(value, objectmodel.Symbolic):
             return value
-        if not isinstance(value, (int, r_uint, r_int, r_longlong, r_ulonglong)):   # can be bool
-            raise TyperError("not an integer: %r" % (value,))
-        if self.lowleveltype == Signed:
-            return intmask(value)
-        if self.lowleveltype == Unsigned:
-            return r_uint(value)
-        if self.lowleveltype == UnsignedLongLong:
-            return r_ulonglong(value)
-        if self.lowleveltype == SignedLongLong:
-            return r_longlong(value)
-        raise NotImplementedError
+        T = typeOf(value)
+        if isinstance(T, Number) or T is Bool:
+            return cast_primitive(self.lowleveltype, value)
+        raise TyperError("not an integer: %r" % (value,))
 
     def get_ll_eq_function(self):
         return None 

Modified: pypy/dist/pypy/rpython/rmodel.py
==============================================================================
--- pypy/dist/pypy/rpython/rmodel.py	(original)
+++ pypy/dist/pypy/rpython/rmodel.py	Wed May 10 19:54:37 2006
@@ -319,9 +319,17 @@
 class IntegerRepr(FloatRepr):
     def __init__(self, lowleveltype, opprefix):
         self.lowleveltype = lowleveltype
-        self.opprefix = opprefix
+        self._opprefix = opprefix
         self.as_int = self
 
+    def _get_opprefix(self):
+        if self._opprefix is None:
+            raise TyperError("arithmetic not supported on %r" %
+                             self.lowleveltype)
+        return self._opprefix
+
+    opprefix =property(_get_opprefix)
+    
 class BoolRepr(IntegerRepr):
     lowleveltype = Bool
     # NB. no 'opprefix' here.  Use 'as_int' systematically.

Modified: pypy/dist/pypy/rpython/rtyper.py
==============================================================================
--- pypy/dist/pypy/rpython/rtyper.py	(original)
+++ pypy/dist/pypy/rpython/rtyper.py	Wed May 10 19:54:37 2006
@@ -22,7 +22,7 @@
      Signed, Unsigned, Float, Char, Bool, Void, \
      LowLevelType, Ptr, ContainerType, \
      FuncType, functionptr, typeOf, RuntimeTypeInfo, \
-     attachRuntimeTypeInfo, Primitive
+     attachRuntimeTypeInfo, Primitive, Number
 from pypy.rpython.ootypesystem import ootype
 from pypy.translator.unsimplify import insert_empty_block
 from pypy.rpython.error import TyperError
@@ -66,9 +66,6 @@
         self.typererror_count = 0
         # 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
         if self.type_system.offers_exceptiondata:
             self.exceptiondata = self.type_system.exceptiondata.ExceptionData(self)
         else:
@@ -89,6 +86,16 @@
             log.info(s)
         self.crash_on_first_typeerror = True
 
+    def getprimitiverepr(self, lltype):
+        try:
+            return self.primitive_to_repr[lltype]
+        except KeyError:
+            pass
+        if isinstance(lltype, Primitive):
+            repr = self.primitive_to_repr[lltype] = self.getrepr(annmodel.lltype_to_annotation(lltype))
+            return repr
+        raise TyperError('There is no primitive repr for %r'%(lltype,))
+    
     def add_wrapper(self, clsdef):
         # record that this class has a wrapper, and what the __init__ is
         cls = clsdef.classdesc.pyobj
@@ -658,7 +665,7 @@
         type.
         """
         if not isinstance(converted_to, Repr):
-            converted_to = self.rtyper.primitive_to_repr[converted_to]
+            converted_to = self.rtyper.getprimitiverepr(converted_to)
         v = self.args_v[arg]
         if isinstance(v, Constant):
             return inputconst(converted_to, v.value)

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	Wed May 10 19:54:37 2006
@@ -3,7 +3,7 @@
 from pypy.annotation import model as annmodel
 from pypy.rpython.test import snippet
 from pypy.rpython.test.test_llinterp import interpret
-from pypy.rpython.rarithmetic import r_uint, r_longlong
+from pypy.rpython.rarithmetic import r_uint, r_longlong, r_ulonglong
 
 
 class TestSnippet(object):
@@ -147,3 +147,28 @@
     res = interpret(f, [20, 4])
     assert type(res) is float
     assert res == 5.0
+
+
+def test_rarithmetic():
+    inttypes = [int, r_uint, r_longlong, r_ulonglong]
+    for inttype in inttypes:
+        c = inttype()
+        def f():
+            return c
+        res = interpret(f, [])
+        assert res == f()
+        assert type(res) == inttype
+
+    for inttype in inttypes:
+        def f():
+            return inttype(0)
+        res = interpret(f, [])
+        assert res == f()
+        assert type(res) == inttype
+
+    for inttype in inttypes:
+        def f(x):
+            return x
+        res = interpret(f, [inttype(0)])
+        assert res == f(inttype(0))
+        assert type(res) == inttype


From arigo at codespeak.net  Wed May 10 21:29:52 2006
From: arigo at codespeak.net (arigo at codespeak.net)
Date: Wed, 10 May 2006 21:29:52 +0200 (CEST)
Subject: [pypy-svn] r27054 - in pypy/dist/pypy/rpython: . lltypesystem/test
Message-ID: <20060510192952.A12AC10088@code0.codespeak.net>

Author: arigo
Date: Wed May 10 21:29:51 2006
New Revision: 27054

Modified:
   pypy/dist/pypy/rpython/llinterp.py
   pypy/dist/pypy/rpython/lltypesystem/test/test_rtagged.py
Log:
Finished writing this test.


Modified: pypy/dist/pypy/rpython/llinterp.py
==============================================================================
--- pypy/dist/pypy/rpython/llinterp.py	(original)
+++ pypy/dist/pypy/rpython/llinterp.py	Wed May 10 21:29:51 2006
@@ -52,9 +52,10 @@
             self.gc = heap.prepare_graphs_and_create_gc(self, flowgraphs)
         if self.TRACING:
             self.tracer = Tracer()
+        self.frame_class = LLFrame
 
     def eval_graph(self, graph, args=()):
-        llframe = LLFrame(graph, args, self)
+        llframe = self.frame_class(graph, args, self)
         if self.tracer:
             self.tracer.start()
         retval = None
@@ -133,7 +134,7 @@
         import exceptions
         klass, inst = exc.args[0], exc.args[1]
         exdata = self.typer.getexceptiondata()
-        frame = LLFrame(None, [], self)
+        frame = self.frame_class(None, [], self)
         old_active_frame = self.active_frame
         try:
             for cls in exceptions.__dict__.values():

Modified: pypy/dist/pypy/rpython/lltypesystem/test/test_rtagged.py
==============================================================================
--- pypy/dist/pypy/rpython/lltypesystem/test/test_rtagged.py	(original)
+++ pypy/dist/pypy/rpython/lltypesystem/test/test_rtagged.py	Wed May 10 21:29:51 2006
@@ -160,9 +160,17 @@
         else:
             x = C(n)
         return x.meth(100)
-    interp, graph = get_interpreter(fn, [1000])
+    interp, graph = get_interpreter(fn, [-1000])
+
     t = interp.typer.annotator.translator
     backend_optimizations(t, propagate=True)
     if conftest.option.view:
         t.view()
-    # XXX finish writing this test
+
+    LLFrame = interp.frame_class
+    class MyFrame(LLFrame):
+        def op_indirect_call(self, f, *args):
+            raise AssertionError("this call should be optimized away")
+    interp.frame_class = MyFrame
+    res = interp.eval_graph(graph, [-1000])
+    assert res == -897


From arigo at codespeak.net  Wed May 10 21:32:18 2006
From: arigo at codespeak.net (arigo at codespeak.net)
Date: Wed, 10 May 2006 21:32:18 +0200 (CEST)
Subject: [pypy-svn] r27055 - pypy/dist/pypy/annotation
Message-ID: <20060510193218.EBD4510088@code0.codespeak.net>

Author: arigo
Date: Wed May 10 21:32:17 2006
New Revision: 27055

Modified:
   pypy/dist/pypy/annotation/policy.py
Log:
An old typo.


Modified: pypy/dist/pypy/annotation/policy.py
==============================================================================
--- pypy/dist/pypy/annotation/policy.py	(original)
+++ pypy/dist/pypy/annotation/policy.py	Wed May 10 21:32:17 2006
@@ -49,7 +49,7 @@
             name, parms = directive_parts
             try:
                 parms = eval("(lambda *parms: parms)(%s" % parms)
-            except KeyboardInterrupt, SystemExit:
+            except (KeyboardInterrupt, SystemExit):
                 raise
             except:
                 raise Exception, "broken specialize directive parms: %s" % directive


From arigo at codespeak.net  Thu May 11 00:21:26 2006
From: arigo at codespeak.net (arigo at codespeak.net)
Date: Thu, 11 May 2006 00:21:26 +0200 (CEST)
Subject: [pypy-svn] r27060 - in pypy/dist/pypy/objspace/std: . test
Message-ID: <20060510222126.DCE351007B@code0.codespeak.net>

Author: arigo
Date: Thu May 11 00:21:00 2006
New Revision: 27060

Modified:
   pypy/dist/pypy/objspace/std/multimethod.py
   pypy/dist/pypy/objspace/std/test/test_multimethod.py
Log:
(arigo, a bit of pedronis)
Starting multimethod table compression.  The new code is not finished,
and not enabled yet.


Modified: pypy/dist/pypy/objspace/std/multimethod.py
==============================================================================
--- pypy/dist/pypy/objspace/std/multimethod.py	(original)
+++ pypy/dist/pypy/objspace/std/multimethod.py	Thu May 11 00:21:00 2006
@@ -89,10 +89,10 @@
         enum_keys((), self.dispatch_tree)
         return result
 
-
 # ____________________________________________________________
+# Installer version 1
 
-class Installer:
+class InstallerVersion1:
     """NOT_RPYTHON"""
 
     mmfunccache = {}
@@ -274,3 +274,284 @@
         #    print "avoided duplicate function", func
         self.to_install.append((target, funcname, func, source, fallback))
         return func
+
+# ____________________________________________________________
+# Installer version 2
+
+class MMDispatcher:
+    """NOT_RPYTHON
+    Explicit dispatcher class.  This is not used in normal execution, which
+    uses the complex Installer below to install single-dispatch methods to
+    achieve the same result.  The MMDispatcher is only used by
+    rpython.lltypesystem.rmultimethod.  It is also nice for documentation.
+    """
+    def __init__(self, multimethod, list_of_typeorders):
+        self.multimethod = multimethod
+        self.list_of_typeorders = list_of_typeorders
+
+    def __call__(self, *args):
+        # for testing only: this is slow
+        i = len(self.multimethod.argnames_before)
+        j = i + self.multimethod.arity
+        k = j + len(self.multimethod.argnames_after)
+        assert len(args) == k
+        prefixargs = args[:i]
+        dispatchargs = args[i:j]
+        suffixargs = args[j:]
+        return self.dispatch([x.__class__ for x in dispatchargs],
+                             prefixargs,
+                             dispatchargs,
+                             suffixargs)
+
+    def dispatch(self, argtypes, prefixargs, args, suffixargs):
+        # for testing only: this is slow
+        def expr(v):
+            if isinstance(v, Call):
+                return v.function(*[expr(w) for w in v.arguments])
+            else:
+                return v
+        e = None
+        for v in self.expressions(argtypes, prefixargs, args, suffixargs):
+            try:
+                return expr(v)
+            except FailedToImplement, e:
+                pass
+        else:
+            raise e or FailedToImplement()
+
+    def expressions(self, argtypes, prefixargs, args, suffixargs):
+        """Lists the possible expressions that call the appropriate
+        function for the given argument types.  Each expression is a Call
+        object.  The intent is that at run-time the first Call that doesn't
+        cause FailedToImplement to be raised is the good one.
+        """
+        prefixargs = tuple(prefixargs)
+        suffixargs = tuple(suffixargs)
+
+        def walktree(node, args_so_far):
+            if isinstance(node, list):
+                for func in node:
+                    if func is not None:
+                        result.append(Call(func, prefixargs +
+                                                 args_so_far +
+                                                 suffixargs))
+            else:
+                index = len(args_so_far)
+                typeorder = self.list_of_typeorders[index]
+                next_type = argtypes[index]
+                for target_type, converter in typeorder[next_type]:
+                    if target_type not in node:
+                        continue
+                    next_arg = args[index]
+                    if converter:
+                        next_arg = Call(converter, prefixargs + (next_arg,))
+                    walktree(node[target_type], args_so_far + (next_arg,))
+
+        result = []
+        walktree(self.multimethod.dispatch_tree, ())
+        return result
+
+
+class Call(object):
+    """ Represents a call expression.
+    The arguments may themselves be Call objects.
+    """
+    def __init__(self, function, arguments):
+        self.function = function
+        self.arguments = arguments
+
+
+class CompressedArray:
+    def __init__(self, null_value, reserved_count):
+        self.null_value = null_value
+        self.reserved_count = reserved_count
+        self.items = [null_value] * reserved_count
+
+    def insert_subarray(self, array):
+        # insert the given array of numbers into the indexlist,
+        # allowing null values to become non-null
+        initial_nulls = 0
+        for item in array:
+            if item != self.null_value:
+                break
+            initial_nulls += 1
+        test = max(self.reserved_count - initial_nulls, 0)
+        while True:
+            while test+len(array) > len(self.items):
+                self.items.append(self.null_value)
+            for i in range(len(array)):
+                if not (array[i] == self.items[test+i] or
+                        array[i] == self.null_value or
+                        self.items[test+i] == self.null_value):
+                    break
+            else:
+                # success
+                for i in range(len(array)):
+                    if array[i] != self.null_value:
+                        self.items[test+i] = array[i]
+                return test
+            test += 1
+
+    def _freeze_(self):
+        return True
+
+
+class MRDTable:
+    # Multi-Method Dispatch Using Multiple Row Displacement,
+    # Candy Pang, Wade Holst, Yuri Leontiev, and Duane Szafron
+    # University of Alberta, Edmonton AB T6G 2H1 Canada
+
+    Counter = 0
+
+    def __init__(self, list_of_types):
+        self.id = MRDTable.Counter
+        MRDTable.Counter += 1
+        self.list_of_types = list_of_types
+        self.typenum = dict(zip(list_of_types, range(len(list_of_types))))
+        self.attrname = '__mrd%d_typenum' % self.id
+        for t1, num in self.typenum.items():
+            setattr(t1, self.attrname, num)
+        self.indexarray = CompressedArray(0, 1)
+
+
+class InstallerVersion2:
+    """NOT_RPYTHON"""
+
+    mrdtables = {}
+
+    def __init__(self, multimethod, prefix, list_of_typeorders,
+                 baked_perform_call=True):
+        print 'InstallerVersion2:', prefix
+        self.multimethod = multimethod
+        self.prefix = prefix
+        self.list_of_typeorders = list_of_typeorders
+        self.baked_perform_call = baked_perform_call
+        self.mmfunccache = {}
+        args = ['arg%d' % i for i in range(multimethod.arity)]
+        self.fnargs = (multimethod.argnames_before + args +
+                       multimethod.argnames_after)
+
+        # compute the complete table
+        assert multimethod.arity == 2
+        assert list_of_typeorders[0] == list_of_typeorders[1]
+
+        lst = list(list_of_typeorders[0])
+        lst.sort()
+        key = tuple(lst)
+        try:
+            self.mrdtable = self.mrdtables[key]
+        except KeyError:
+            self.mrdtable = self.mrdtables[key] = MRDTable(key)
+
+        dispatcher = MMDispatcher(multimethod, list_of_typeorders)
+        self.table = {}
+        for t0 in list_of_typeorders[0]:
+            for t1 in list_of_typeorders[1]:
+                calllist = dispatcher.expressions([t0, t1],
+                                                  multimethod.argnames_before,
+                                                  args,
+                                                  multimethod.argnames_after)
+                if calllist:
+                    self.table[t0, t1] = calllist
+
+    def is_empty(self):
+        return len(self.table) == 0
+
+    def install(self):
+        null_func = self.build_function(self.prefix + '_fail', [], True)
+        if self.is_empty():
+            return null_func
+
+        funcarray = CompressedArray(null_func, 1)
+        indexarray = self.mrdtable.indexarray
+        lst = self.mrdtable.list_of_types
+        indexline = []
+        for t0 in lst:
+            flatline = []
+            for t1 in lst:
+                calllist = self.table.get((t0, t1), [])
+                funcname = '_'.join([self.prefix, t0.__name__, t1.__name__])
+                fn = self.build_function(funcname, calllist)
+                flatline.append(fn)
+            index = funcarray.insert_subarray(flatline)
+            indexline.append(index)
+
+        master_index = indexarray.insert_subarray(indexline)
+
+        print master_index
+        print indexarray.items
+        print funcarray.items
+
+        attrname = self.mrdtable.attrname
+        exprfn = "funcarray.items[indexarray.items[%d + arg0.%s] + arg1.%s]" %(
+            master_index, attrname, attrname)
+        expr = Call(exprfn, self.fnargs)
+        return self.build_function(self.prefix + '_perform_call',
+                                   [expr], True,
+                                   indexarray = indexarray,
+                                   funcarray = funcarray)
+
+    def build_function(self, funcname, calllist, is_perform_call=False,
+                       **extranames):
+        def invent_name(obj):
+            if isinstance(obj, str):
+                return obj
+            name = obj.__name__
+            n = 1
+            while name in miniglobals:
+                n += 1
+                name = '%s%d' % (obj.__name__, n)
+            miniglobals[name] = obj
+            return name
+
+        def expr(v):
+            if isinstance(v, Call):
+                return '%s(%s)' % (invent_name(v.function),
+                                   ', '.join([expr(w) for w in v.arguments]))
+            else:
+                return v
+
+        fallback = len(calllist) == 0
+        if fallback:
+            miniglobals = {'raiseFailedToImplement': raiseFailedToImplement}
+            bodylines = ['return raiseFailedToImplement()']
+        else:
+            miniglobals = {'FailedToImplement': FailedToImplement}
+            miniglobals.update(extranames)
+            bodylines = []
+            for v in calllist[:-1]:
+                bodylines.append('try:')
+                bodylines.append('    return %s' % expr(v))
+                bodylines.append('except FailedToImplement:')
+                bodylines.append('    pass')
+            bodylines.append('return %s' % expr(calllist[-1]))
+
+        if is_perform_call and not self.baked_perform_call:
+            return self.fnargs, bodylines[0][len('return '):], miniglobals, fallback
+
+        # indent mode
+        bodylines = ['    ' + line for line in bodylines]
+        bodylines.append('')
+        source = '\n'.join(bodylines)
+
+        # XXX find a better place (or way) to avoid duplicate functions 
+        l = miniglobals.items()
+        l.sort()
+        l = tuple(l)
+        key = (source, l)
+        try: 
+            func = self.mmfunccache[key]
+        except KeyError: 
+            source = 'def %s(%s):\n%s' % (funcname, ', '.join(self.fnargs),
+                                          source)
+            exec compile2(source) in miniglobals
+            func = miniglobals[funcname]
+            self.mmfunccache[key] = func 
+        #else: 
+        #    print "avoided duplicate function", func
+        return func
+
+# ____________________________________________________________
+# Selection of the version to use
+
+Installer = InstallerVersion1

Modified: pypy/dist/pypy/objspace/std/test/test_multimethod.py
==============================================================================
--- pypy/dist/pypy/objspace/std/test/test_multimethod.py	(original)
+++ pypy/dist/pypy/objspace/std/test/test_multimethod.py	Thu May 11 00:21:00 2006
@@ -68,15 +68,17 @@
 def test_not_baked():
     add2 = add.install('__add2', [typeorder, typeorder],baked_perform_call=False)
     assert add2[0] == ['space', 'arg0', 'arg1']
-    assert add2[1] == 'arg0.__add2(space, arg1)'
+    if Installer is InstallerVersion1:
+        assert add2[1] == 'arg0.__add2(space, arg1)'
     assert isinstance(add2[2], dict)
     assert not add2[3]
 
 def test_empty():
     add3_installer = Installer(add, '__add3', [{},{}])
     assert add3_installer.is_empty()
-    assert len(add3_installer.to_install) == 1
-    assert add3_installer.to_install[0][0] is None
+    if Installer is InstallerVersion1:
+        assert len(add3_installer.to_install) == 1
+        assert add3_installer.to_install[0][0] is None
 
 def test_empty_direct():
     assert not add.install_if_not_empty('__add4', [{},{}])
@@ -85,10 +87,23 @@
 def test_empty_not_baked():
     add5_installer = Installer(add, '__add5', [{},{}], baked_perform_call=False)
     assert add5_installer.is_empty()
-    assert len(add5_installer.to_install) == 0
+    if Installer is InstallerVersion1:
+        assert len(add5_installer.to_install) == 0
     add5 = add5_installer.install()
     assert add5[0] == ['space', 'arg0', 'arg1']
     assert add5[1] == 'raiseFailedToImplement()'
     assert isinstance(add5[2], dict)
     assert add5[3]
     
+def test_mmdispatcher():
+    add2 = MMDispatcher(add, [typeorder, typeorder])
+    space = 'space'
+    w_x = W_IntObject()
+    w_s = W_StringObject()
+    w_b1 = W_BoolObject()
+    w_b2 = W_BoolObject()
+    assert add2(space, w_x, w_b1) == 'fine'
+    assert add2(space, w_b2, w_x) == 'fine'
+    assert add2(space, w_b1, w_b2) == 'fine'
+    raises(FailedToImplement, "add2(space, w_b2, w_s)")
+    raises(FailedToImplement, "add2(space, w_s, w_b1)")


From ericvrp at codespeak.net  Thu May 11 09:56:09 2006
From: ericvrp at codespeak.net (ericvrp at codespeak.net)
Date: Thu, 11 May 2006 09:56:09 +0200 (CEST)
Subject: [pypy-svn] r27065 - in pypy/dist/pypy: interpreter
	module/_pickle_support objspace/std
Message-ID: <20060511075609.BF15B1008D@code0.codespeak.net>

Author: ericvrp
Date: Thu May 11 09:56:07 2006
New Revision: 27065

Modified:
   pypy/dist/pypy/interpreter/pycode.py
   pypy/dist/pypy/module/_pickle_support/__init__.py
   pypy/dist/pypy/module/_pickle_support/maker.py
   pypy/dist/pypy/objspace/std/dicttype.py
Log:
Still struggling with pickling dictiterator. (still disabled)


Modified: pypy/dist/pypy/interpreter/pycode.py
==============================================================================
--- pypy/dist/pypy/interpreter/pycode.py	(original)
+++ pypy/dist/pypy/interpreter/pycode.py	Thu May 11 09:56:07 2006
@@ -10,7 +10,6 @@
 from pypy.interpreter.error import OperationError
 from pypy.interpreter.gateway import NoneNotWrapped 
 from pypy.interpreter.baseobjspace import ObjSpace, W_Root 
-from pypy.interpreter.mixedmodule import MixedModule
 from pypy.rpython.rarithmetic import intmask
 
 # helper
@@ -401,6 +400,7 @@
     descr_code__new__.unwrap_spec = unwrap_spec 
 
     def descr__reduce__(self, space):
+        from pypy.interpreter.mixedmodule import MixedModule
         w_mod    = space.getbuiltinmodule('_pickle_support')
         mod      = space.interp_w(MixedModule, w_mod)
         new_inst = mod.get('code_new')

Modified: pypy/dist/pypy/module/_pickle_support/__init__.py
==============================================================================
--- pypy/dist/pypy/module/_pickle_support/__init__.py	(original)
+++ pypy/dist/pypy/module/_pickle_support/__init__.py	Thu May 11 09:56:07 2006
@@ -7,9 +7,11 @@
     }
 
     interpleveldefs = {
-        'cell_new'   : 'maker.cell_new',
-        'code_new'   : 'maker.code_new',
-        'func_new'   : 'maker.func_new',
-        'module_new' : 'maker.module_new',
-        'method_new' : 'maker.method_new',
+        'cell_new'     : 'maker.cell_new',
+        'code_new'     : 'maker.code_new',
+        'func_new'     : 'maker.func_new',
+        'module_new'   : 'maker.module_new',
+        'method_new'   : 'maker.method_new',
+        'dictiter_new' : 'maker.dictiter_new',
+        'seqiter_new'  : 'maker.seqiter_new',
     }

Modified: pypy/dist/pypy/module/_pickle_support/maker.py
==============================================================================
--- pypy/dist/pypy/module/_pickle_support/maker.py	(original)
+++ pypy/dist/pypy/module/_pickle_support/maker.py	Thu May 11 09:56:07 2006
@@ -5,6 +5,8 @@
 from pypy.rpython.objectmodel import instantiate
 from pypy.interpreter.argument import Arguments
 from pypy.interpreter.baseobjspace import ObjSpace, W_Root
+from pypy.objspace.std.dicttype import dictiter_typedef
+from pypy.objspace.std.itertype import iter_typedef as seqiter_typedef
 
 
 #note: for now we don't use the actual value when creating the Cell.
@@ -32,3 +34,30 @@
     w_type = space.gettypeobject(Method.typedef)
     return space.call_args(w_type, __args__)
 method_new.unwrap_spec = [ObjSpace, Arguments]
+
+#XXX this does not work yet
+def dictiter_new(space, w_dictitertype, __args__):
+    print "dictiter_new here 1)", space, w_dictitertype
+    #w_type = space.gettypeobject(dictiter_typedef)
+    #print "dictiter_new here 2)", w_type
+    #a = space.call_args(w_type, __args__)
+    #print "dictiter_new here 3)", a
+    #return a
+    from pypy.objspace.std.dictobject import W_DictIterObject
+    w_obj = space.allocate_instance(W_DictIterObject, w_dictitertype)
+    print "dictiter_new here 2)", w_obj
+    W_DictIterObject.__init__(w_obj, space)
+    print "dictiter_new here 3)", w_obj
+    return w_obj
+dictiter_new.unwrap_spec = [ObjSpace, W_Root, Arguments]
+
+#XXX this doesn't work either
+def seqiter_new(space, w_seqitertype, __args__):
+    raise 'No seqiter_new (pickle support) yet'
+    print "seqiter_new here 1)", space, __args__
+    w_type = space.gettypeobject(seqiter_typedef)
+    print "seqiter_new here 2)", w_type
+    a = space.call_args(w_type, __args__)
+    print "seqiter_new here 3)", a
+    return a
+seqiter_new.unwrap_spec = [ObjSpace, W_Root, Arguments]

Modified: pypy/dist/pypy/objspace/std/dicttype.py
==============================================================================
--- pypy/dist/pypy/objspace/std/dicttype.py	(original)
+++ pypy/dist/pypy/objspace/std/dicttype.py	Thu May 11 09:56:07 2006
@@ -122,6 +122,38 @@
     )
 dict_typedef.registermethods(globals())
 
+# ____________________________________________________________
+
+def descr_dictiter__reduce__(space, w_subtype):
+    from pypy.interpreter.mixedmodule import MixedModule
+    w_mod    = space.getbuiltinmodule('_pickle_support')
+    mod      = space.interp_w(MixedModule, w_mod)
+    new_inst = mod.get('dictiter_new')
+    w        = space.wrap
+    tup      = [
+        #w(10),
+        #w(self.co_argcount), 
+        #w(self.co_nlocals), 
+        #w(self.co_stacksize), 
+        #w(self.co_flags),
+        #w(self.co_code), 
+        #space.newtuple(self.co_consts_w), 
+        #space.newtuple(self.co_names_w), 
+        #space.newtuple([w(v) for v in self.co_varnames]), 
+        #w(self.co_filename),
+        #w(self.co_name), 
+        #w(self.co_firstlineno),
+        #w(self.co_lnotab), 
+        #space.newtuple([w(v) for v in self.co_freevars]),
+        #space.newtuple([w(v) for v in self.co_cellvars]),
+        #hidden_applevel=False, magic = 62061 | 0x0a0d0000
+    ]
+    return space.newtuple([new_inst, space.newtuple(tup)])
+
+# ____________________________________________________________
 
 dictiter_typedef = StdTypeDef("dictionaryiterator",
+    __reduce__ = gateway.interp2app(descr_dictiter__reduce__,
+                           unwrap_spec=[gateway.ObjSpace,gateway.W_Root]),
     )
+#note: registering in dictobject.py


From arigo at codespeak.net  Thu May 11 12:16:42 2006
From: arigo at codespeak.net (arigo at codespeak.net)
Date: Thu, 11 May 2006 12:16:42 +0200 (CEST)
Subject: [pypy-svn] r27066 - pypy/dist/pypy/objspace/std
Message-ID: <20060511101642.BA74A10087@code0.codespeak.net>

Author: arigo
Date: Thu May 11 12:16:36 2006
New Revision: 27066

Modified:
   pypy/dist/pypy/objspace/std/multimethod.py
Log:
Fixed multimethod installer version 2 to check the types of the
arguments.  Now the (very limited) test_multimethod passes with
this installer too.


Modified: pypy/dist/pypy/objspace/std/multimethod.py
==============================================================================
--- pypy/dist/pypy/objspace/std/multimethod.py	(original)
+++ pypy/dist/pypy/objspace/std/multimethod.py	Thu May 11 12:16:36 2006
@@ -278,7 +278,7 @@
 # ____________________________________________________________
 # Installer version 2
 
-class MMDispatcher:
+class MMDispatcher(object):
     """NOT_RPYTHON
     Explicit dispatcher class.  This is not used in normal execution, which
     uses the complex Installer below to install single-dispatch methods to
@@ -361,12 +361,16 @@
         self.arguments = arguments
 
 
-class CompressedArray:
+class CompressedArray(object):
     def __init__(self, null_value, reserved_count):
         self.null_value = null_value
         self.reserved_count = reserved_count
         self.items = [null_value] * reserved_count
 
+    def ensure_length(self, newlen):
+        if newlen > len(self.items):
+            self.items.extend([self.null_value] * (newlen - len(self.items)))
+
     def insert_subarray(self, array):
         # insert the given array of numbers into the indexlist,
         # allowing null values to become non-null
@@ -377,8 +381,7 @@
             initial_nulls += 1
         test = max(self.reserved_count - initial_nulls, 0)
         while True:
-            while test+len(array) > len(self.items):
-                self.items.append(self.null_value)
+            self.ensure_length(test+len(array))
             for i in range(len(array)):
                 if not (array[i] == self.items[test+i] or
                         array[i] == self.null_value or
@@ -396,7 +399,7 @@
         return True
 
 
-class MRDTable:
+class MRDTable(object):
     # Multi-Method Dispatch Using Multiple Row Displacement,
     # Candy Pang, Wade Holst, Yuri Leontiev, and Duane Szafron
     # University of Alberta, Edmonton AB T6G 2H1 Canada
@@ -412,9 +415,103 @@
         for t1, num in self.typenum.items():
             setattr(t1, self.attrname, num)
         self.indexarray = CompressedArray(0, 1)
+        self.allarrays = [self.indexarray]
+
+    def normalize_length(self, next_array):
+        self.allarrays.append(next_array)
+        length = max([len(a.items) for a in self.allarrays])
+        for a in self.allarrays:
+            a.ensure_length(length)
+
+
+class FuncEntry(object):
+
+    def __init__(self, bodylines, miniglobals, fallback):
+        self.body = '\n    '.join(bodylines)
+        self.miniglobals = miniglobals
+        self.fallback = fallback
+        self.possiblenames = []
+        self.typetree = {}
+        self._function = None
+
+    def key(self):
+        lst = self.miniglobals.items()
+        lst.sort()
+        return self.body, tuple(lst)
 
+    def make_function(self, fnargs, nbargs_before, mrdtable):
+        if self._function is not None:
+            return self._function
+        name = min(self.possiblenames)   # pick a random one, but consistently
+        self.compress_typechecks(mrdtable)
+        checklines = self.generate_typechecks(fnargs[nbargs_before:], mrdtable)
+        source = 'def %s(%s):\n    %s\n    %s\n' % (name, ', '.join(fnargs),
+                                                    '\n    '.join(checklines),
+                                                    self.body)
+        print '_' * 60
+        print self.possiblenames
+        print source
+        exec compile2(source) in self.miniglobals
+        self._function = self.miniglobals[name]
+        return self._function
+
+    def register_valid_types(self, typenums):
+        node = self.typetree
+        for n in typenums[:-1]:
+            if node is True:
+                return
+            node = node.setdefault(n, {})
+        if node is True:
+            return
+        node[typenums[-1]] = True
+
+    def no_typecheck(self):
+        self.typetree = True
+
+    def compress_typechecks(self, mrdtable):
+        def full(node):
+            if node is True:
+                return 1
+            fulls = 0
+            for key, subnode in node.items():
+                if full(subnode):
+                    node[key] = True
+                    fulls += 1
+            if fulls == types_total:
+                return 1
+            return 0
+
+        types_total = len(mrdtable.list_of_types)
+        if full(self.typetree):
+            self.typetree = True
+
+    def generate_typechecks(self, args, mrdtable):
+        def generate(node, level=0):
+            indent = '    '*level
+            if node is True:
+                result.append('%spass' % (indent,))
+                return
+            if not node:
+                result.append('%sraise FailedToImplement' % (indent,))
+                return
+            keyword = 'if'
+            for key, subnode in node.items():
+                result.append('%s%s %s == %d:' % (indent, keyword,
+                                                  typeidexprs[level], key))
+                generate(subnode, level+1)
+                keyword = 'elif'
+            result.append('%selse:' % (indent,))
+            result.append('%s    raise FailedToImplement' % (indent,))
+
+        typeidexprs = ['%s.%s' % (arg, mrdtable.attrname) for arg in args]
+        result = []
+        generate(self.typetree)
+        if result == ['pass']:
+            del result[:]
+        return result
 
-class InstallerVersion2:
+
+class InstallerVersion2(object):
     """NOT_RPYTHON"""
 
     mrdtables = {}
@@ -458,26 +555,36 @@
         return len(self.table) == 0
 
     def install(self):
-        null_func = self.build_function(self.prefix + '_fail', [], True)
+        nskip = len(self.multimethod.argnames_before)
+        null_entry = self.build_funcentry(self.prefix + '0fail', [])
+        null_entry.no_typecheck()
         if self.is_empty():
-            return null_func
+            return self.answer(null_entry)
 
-        funcarray = CompressedArray(null_func, 1)
+        entryarray = CompressedArray(null_entry, 1)
         indexarray = self.mrdtable.indexarray
         lst = self.mrdtable.list_of_types
         indexline = []
-        for t0 in lst:
+        for num0, t0 in enumerate(lst):
             flatline = []
-            for t1 in lst:
+            for num1, t1 in enumerate(lst):
                 calllist = self.table.get((t0, t1), [])
                 funcname = '_'.join([self.prefix, t0.__name__, t1.__name__])
-                fn = self.build_function(funcname, calllist)
-                flatline.append(fn)
-            index = funcarray.insert_subarray(flatline)
+                entry = self.build_funcentry(funcname, calllist)
+                entry.register_valid_types((num0, num1))
+                flatline.append(entry)
+            index = entryarray.insert_subarray(flatline)
             indexline.append(index)
 
         master_index = indexarray.insert_subarray(indexline)
 
+        null_func = null_entry.make_function(self.fnargs, nskip, self.mrdtable)
+        funcarray = CompressedArray(null_func, 0)
+        for entry in entryarray.items:
+            func = entry.make_function(self.fnargs, nskip, self.mrdtable)
+            funcarray.items.append(func)
+        self.mrdtable.normalize_length(funcarray)
+
         print master_index
         print indexarray.items
         print funcarray.items
@@ -486,13 +593,23 @@
         exprfn = "funcarray.items[indexarray.items[%d + arg0.%s] + arg1.%s]" %(
             master_index, attrname, attrname)
         expr = Call(exprfn, self.fnargs)
-        return self.build_function(self.prefix + '_perform_call',
-                                   [expr], True,
-                                   indexarray = indexarray,
-                                   funcarray = funcarray)
+        entry = self.build_funcentry(self.prefix + '0perform_call',
+                                     [expr],
+                                     indexarray = indexarray,
+                                     funcarray = funcarray)
+        entry.no_typecheck()
+        return self.answer(entry)
+
+    def answer(self, entry):
+        if self.baked_perform_call:
+            nskip = len(self.multimethod.argnames_before)
+            return entry.make_function(self.fnargs, nskip, self.mrdtable)
+        else:
+            assert entry.body.startswith('return ')
+            expr = entry.body[len('return '):]
+            return self.fnargs, expr, entry.miniglobals, entry.fallback
 
-    def build_function(self, funcname, calllist, is_perform_call=False,
-                       **extranames):
+    def build_funcentry(self, funcname, calllist, **extranames):
         def invent_name(obj):
             if isinstance(obj, str):
                 return obj
@@ -526,30 +643,14 @@
                 bodylines.append('    pass')
             bodylines.append('return %s' % expr(calllist[-1]))
 
-        if is_perform_call and not self.baked_perform_call:
-            return self.fnargs, bodylines[0][len('return '):], miniglobals, fallback
-
-        # indent mode
-        bodylines = ['    ' + line for line in bodylines]
-        bodylines.append('')
-        source = '\n'.join(bodylines)
-
-        # XXX find a better place (or way) to avoid duplicate functions 
-        l = miniglobals.items()
-        l.sort()
-        l = tuple(l)
-        key = (source, l)
-        try: 
-            func = self.mmfunccache[key]
-        except KeyError: 
-            source = 'def %s(%s):\n%s' % (funcname, ', '.join(self.fnargs),
-                                          source)
-            exec compile2(source) in miniglobals
-            func = miniglobals[funcname]
-            self.mmfunccache[key] = func 
-        #else: 
-        #    print "avoided duplicate function", func
-        return func
+        entry = FuncEntry(bodylines, miniglobals, fallback)
+        key = entry.key()
+        try:
+            entry = self.mmfunccache[key]
+        except KeyError:
+            self.mmfunccache[key] = entry
+        entry.possiblenames.append(funcname)
+        return entry
 
 # ____________________________________________________________
 # Selection of the version to use


From cfbolz at codespeak.net  Thu May 11 13:41:40 2006
From: cfbolz at codespeak.net (cfbolz at codespeak.net)
Date: Thu, 11 May 2006 13:41:40 +0200 (CEST)
Subject: [pypy-svn] r27067 - pypy/dist/pypy/objspace/std
Message-ID: <20060511114140.6454C1007B@code0.codespeak.net>

Author: cfbolz
Date: Thu May 11 13:41:39 2006
New Revision: 27067

Modified:
   pypy/dist/pypy/objspace/std/multimethod.py
Log:
add link


Modified: pypy/dist/pypy/objspace/std/multimethod.py
==============================================================================
--- pypy/dist/pypy/objspace/std/multimethod.py	(original)
+++ pypy/dist/pypy/objspace/std/multimethod.py	Thu May 11 13:41:39 2006
@@ -403,6 +403,7 @@
     # Multi-Method Dispatch Using Multiple Row Displacement,
     # Candy Pang, Wade Holst, Yuri Leontiev, and Duane Szafron
     # University of Alberta, Edmonton AB T6G 2H1 Canada
+    # can be found on http://web.cs.ualberta.ca/~yuri/publ.htm
 
     Counter = 0
 


From arigo at codespeak.net  Thu May 11 13:45:51 2006
From: arigo at codespeak.net (arigo at codespeak.net)
Date: Thu, 11 May 2006 13:45:51 +0200 (CEST)
Subject: [pypy-svn] r27068 - pypy/dist/pypy/objspace/std
Message-ID: <20060511114551.087F41007B@code0.codespeak.net>

Author: arigo
Date: Thu May 11 13:45:50 2006
New Revision: 27068

Modified:
   pypy/dist/pypy/objspace/std/multimethod.py
   pypy/dist/pypy/objspace/std/stdtypedef.py
Log:
A working version of compressed multimethod.
Still quite slow at start-up.


Modified: pypy/dist/pypy/objspace/std/multimethod.py
==============================================================================
--- pypy/dist/pypy/objspace/std/multimethod.py	(original)
+++ pypy/dist/pypy/objspace/std/multimethod.py	Thu May 11 13:45:50 2006
@@ -39,17 +39,21 @@
             types, order)
         lst[order] = function
 
-    def install(self, prefix, list_of_typeorders, baked_perform_call=True):
+    def install(self, prefix, list_of_typeorders, baked_perform_call=True,
+                base_typeorder=None):
         "NOT_RPYTHON: initialization-time only"
         assert len(list_of_typeorders) == self.arity
         installer = Installer(self, prefix, list_of_typeorders,
-                              baked_perform_call=baked_perform_call)
+                              baked_perform_call=baked_perform_call,
+                              base_typeorder=base_typeorder)
         return installer.install()
 
-    def install_if_not_empty(self, prefix, list_of_typeorders):
+    def install_if_not_empty(self, prefix, list_of_typeorders,
+                             base_typeorder=None):
         "NOT_RPYTHON: initialization-time only"
         assert len(list_of_typeorders) == self.arity
-        installer = Installer(self, prefix, list_of_typeorders)
+        installer = Installer(self, prefix, list_of_typeorders,
+                              base_typeorder=base_typeorder)
         if installer.is_empty():
             return None
         else:
@@ -99,7 +103,8 @@
 
     prefix_memo = {}
 
-    def __init__(self, multimethod, prefix, list_of_typeorders, baked_perform_call=True):
+    def __init__(self, multimethod, prefix, list_of_typeorders,
+                 baked_perform_call=True, base_typeorder=None):
         self.multimethod = multimethod
         # avoid prefix clashes, user code should supply different prefixes
         # itself for nice names in tracebacks
@@ -362,10 +367,9 @@
 
 
 class CompressedArray(object):
-    def __init__(self, null_value, reserved_count):
+    def __init__(self, null_value):
         self.null_value = null_value
-        self.reserved_count = reserved_count
-        self.items = [null_value] * reserved_count
+        self.items = [null_value]
 
     def ensure_length(self, newlen):
         if newlen > len(self.items):
@@ -374,12 +378,9 @@
     def insert_subarray(self, array):
         # insert the given array of numbers into the indexlist,
         # allowing null values to become non-null
-        initial_nulls = 0
-        for item in array:
-            if item != self.null_value:
-                break
-            initial_nulls += 1
-        test = max(self.reserved_count - initial_nulls, 0)
+        if array.count(self.null_value) == len(array):
+            return 0
+        test = 1
         while True:
             self.ensure_length(test+len(array))
             for i in range(len(array)):
@@ -415,14 +416,11 @@
         self.attrname = '__mrd%d_typenum' % self.id
         for t1, num in self.typenum.items():
             setattr(t1, self.attrname, num)
-        self.indexarray = CompressedArray(0, 1)
-        self.allarrays = [self.indexarray]
+        self.indexarray = CompressedArray(0)
 
     def normalize_length(self, next_array):
-        self.allarrays.append(next_array)
-        length = max([len(a.items) for a in self.allarrays])
-        for a in self.allarrays:
-            a.ensure_length(length)
+        # make sure that the indexarray is not smaller than any funcarray
+        self.indexarray.ensure_length(len(next_array.items))
 
 
 class FuncEntry(object):
@@ -446,12 +444,14 @@
         name = min(self.possiblenames)   # pick a random one, but consistently
         self.compress_typechecks(mrdtable)
         checklines = self.generate_typechecks(fnargs[nbargs_before:], mrdtable)
-        source = 'def %s(%s):\n    %s\n    %s\n' % (name, ', '.join(fnargs),
-                                                    '\n    '.join(checklines),
-                                                    self.body)
-        print '_' * 60
-        print self.possiblenames
-        print source
+        if checklines == ['pass']:
+            body = self.body
+        else:
+            checklines.append(self.body)
+            body = '\n    '.join(checklines)
+        source = 'def %s(%s):\n    %s\n' % (name, ', '.join(fnargs), body)
+        #print '_' * 60
+        #print source
         exec compile2(source) in self.miniglobals
         self._function = self.miniglobals[name]
         return self._function
@@ -507,8 +507,6 @@
         typeidexprs = ['%s.%s' % (arg, mrdtable.attrname) for arg in args]
         result = []
         generate(self.typetree)
-        if result == ['pass']:
-            del result[:]
         return result
 
 
@@ -518,8 +516,8 @@
     mrdtables = {}
 
     def __init__(self, multimethod, prefix, list_of_typeorders,
-                 baked_perform_call=True):
-        print 'InstallerVersion2:', prefix
+                 baked_perform_call=True, base_typeorder=None):
+        #print 'InstallerVersion2:', prefix
         self.multimethod = multimethod
         self.prefix = prefix
         self.list_of_typeorders = list_of_typeorders
@@ -530,10 +528,12 @@
                        multimethod.argnames_after)
 
         # compute the complete table
-        assert multimethod.arity == 2
-        assert list_of_typeorders[0] == list_of_typeorders[1]
+        base_typeorder = base_typeorder or list_of_typeorders[0]
+        for typeorder in list_of_typeorders:
+            for t1 in typeorder:
+                assert t1 in base_typeorder
 
-        lst = list(list_of_typeorders[0])
+        lst = list(base_typeorder)
         lst.sort()
         key = tuple(lst)
         try:
@@ -543,61 +543,87 @@
 
         dispatcher = MMDispatcher(multimethod, list_of_typeorders)
         self.table = {}
-        for t0 in list_of_typeorders[0]:
-            for t1 in list_of_typeorders[1]:
-                calllist = dispatcher.expressions([t0, t1],
+        def buildtable(prefixtypes):
+            if len(prefixtypes) == multimethod.arity:
+                calllist = dispatcher.expressions(prefixtypes,
                                                   multimethod.argnames_before,
                                                   args,
                                                   multimethod.argnames_after)
                 if calllist:
-                    self.table[t0, t1] = calllist
+                    self.table[prefixtypes] = calllist
+            else:
+                typeorder = list_of_typeorders[len(prefixtypes)]
+                for t1 in typeorder:
+                    buildtable(prefixtypes + (t1,))
+        buildtable(())
 
     def is_empty(self):
         return len(self.table) == 0
 
     def install(self):
         nskip = len(self.multimethod.argnames_before)
-        null_entry = self.build_funcentry(self.prefix + '0fail', [])
+        null_entry = self.build_funcentry(self.prefix + '_0_fail', [])
         null_entry.no_typecheck()
         if self.is_empty():
             return self.answer(null_entry)
 
-        entryarray = CompressedArray(null_entry, 1)
+        entryarray = CompressedArray(null_entry)
         indexarray = self.mrdtable.indexarray
         lst = self.mrdtable.list_of_types
         indexline = []
-        for num0, t0 in enumerate(lst):
-            flatline = []
-            for num1, t1 in enumerate(lst):
-                calllist = self.table.get((t0, t1), [])
-                funcname = '_'.join([self.prefix, t0.__name__, t1.__name__])
+
+        def compress(typesprefix, typesnum):
+            if len(typesprefix) == self.multimethod.arity:
+                calllist = self.table.get(typesprefix, [])
+                funcname = [self.prefix]
+                for t1 in typesprefix:
+                    funcname.append(t1.__name__)
+                funcname = '_'.join(funcname)
                 entry = self.build_funcentry(funcname, calllist)
-                entry.register_valid_types((num0, num1))
-                flatline.append(entry)
-            index = entryarray.insert_subarray(flatline)
-            indexline.append(index)
+                entry.register_valid_types(typesnum)
+                return entry
+            else:
+                flatline = []
+                for num1, t1 in enumerate(lst):
+                    item = compress(typesprefix + (t1,), typesnum + (num1,))
+                    flatline.append(item)
+                if len(typesprefix) == self.multimethod.arity - 1:
+                    array = entryarray
+                else:
+                    array = indexarray
+                return array.insert_subarray(flatline)
 
-        master_index = indexarray.insert_subarray(indexline)
+        master_index = compress((), ())
 
         null_func = null_entry.make_function(self.fnargs, nskip, self.mrdtable)
-        funcarray = CompressedArray(null_func, 0)
-        for entry in entryarray.items:
+        funcarray = CompressedArray(null_func)
+        # round up the length to a power of 2
+        N = 1
+        while N < len(entryarray.items):
+            N *= 2
+        funcarray.ensure_length(N)
+        for i, entry in enumerate(entryarray.items):
             func = entry.make_function(self.fnargs, nskip, self.mrdtable)
-            funcarray.items.append(func)
+            funcarray.items[i] = func
         self.mrdtable.normalize_length(funcarray)
 
-        print master_index
-        print indexarray.items
-        print funcarray.items
+        #print master_index
+        #print indexarray.items
+        #print funcarray.items
 
         attrname = self.mrdtable.attrname
-        exprfn = "funcarray.items[indexarray.items[%d + arg0.%s] + arg1.%s]" %(
-            master_index, attrname, attrname)
+        exprfn = "%d" % master_index
+        for n in range(self.multimethod.arity-1):
+            exprfn = "indexarray.items[%s + arg%d.%s]" % (exprfn, n, attrname)
+        n = self.multimethod.arity-1
+        exprfn = "funcarray.items[(%s + arg%d.%s) & mmmask]" % (exprfn, n,
+                                                                attrname)
         expr = Call(exprfn, self.fnargs)
-        entry = self.build_funcentry(self.prefix + '0perform_call',
+        entry = self.build_funcentry(self.prefix + '_0_perform_call',
                                      [expr],
                                      indexarray = indexarray,
-                                     funcarray = funcarray)
+                                     funcarray = funcarray,
+                                     mmmask = N-1)
         entry.no_typecheck()
         return self.answer(entry)
 

Modified: pypy/dist/pypy/objspace/std/stdtypedef.py
==============================================================================
--- pypy/dist/pypy/objspace/std/stdtypedef.py	(original)
+++ pypy/dist/pypy/objspace/std/stdtypedef.py	Thu May 11 13:45:50 2006
@@ -279,7 +279,8 @@
             prefix, list_of_typeorders = sliced_typeorders(
                 space.model.typeorder, multimethod, typedef, i, local=local)
             exprargs, expr, miniglobals, fallback = multimethod.install(prefix, list_of_typeorders,
-                                                                        baked_perform_call=False)
+                                                                        baked_perform_call=False,
+                                                                        base_typeorder=space.model.typeorder)
             if fallback:
                 return None   # skip empty multimethods
             trampoline = make_perform_trampoline(prefix, exprargs, expr, miniglobals,


From arigo at codespeak.net  Thu May 11 13:58:59 2006
From: arigo at codespeak.net (arigo at codespeak.net)
Date: Thu, 11 May 2006 13:58:59 +0200 (CEST)
Subject: [pypy-svn] r27070 - pypy/dist/pypy/objspace/std
Message-ID: <20060511115859.F04761007B@code0.codespeak.net>

Author: arigo
Date: Thu May 11 13:58:58 2006
New Revision: 27070

Modified:
   pypy/dist/pypy/objspace/std/multimethod.py
Log:
Fixed the start-up speed problem with a short hack:
ask the InstallerVersion1 if it thinks there is a chance
to see anything in the given area...


Modified: pypy/dist/pypy/objspace/std/multimethod.py
==============================================================================
--- pypy/dist/pypy/objspace/std/multimethod.py	(original)
+++ pypy/dist/pypy/objspace/std/multimethod.py	Thu May 11 13:58:58 2006
@@ -290,6 +290,8 @@
     achieve the same result.  The MMDispatcher is only used by
     rpython.lltypesystem.rmultimethod.  It is also nice for documentation.
     """
+    _revcache = None
+
     def __init__(self, multimethod, list_of_typeorders):
         self.multimethod = multimethod
         self.list_of_typeorders = list_of_typeorders
@@ -356,6 +358,16 @@
         walktree(self.multimethod.dispatch_tree, ())
         return result
 
+    def anychance(self, typesprefix):
+        # is there any chance that a list of types starting with typesprefix
+        # could lead to a successful dispatch?
+        if self._revcache is None:
+            # quick hack!
+            installer = InstallerVersion1(self.multimethod, 'X',
+                                          self.list_of_typeorders)
+            self._revcache = dict.fromkeys(installer.subtree_cache)
+        return tuple(typesprefix) in self._revcache
+
 
 class Call(object):
     """ Represents a call expression.
@@ -551,11 +563,12 @@
                                                   multimethod.argnames_after)
                 if calllist:
                     self.table[prefixtypes] = calllist
-            else:
+            elif dispatcher.anychance(prefixtypes):
                 typeorder = list_of_typeorders[len(prefixtypes)]
                 for t1 in typeorder:
                     buildtable(prefixtypes + (t1,))
         buildtable(())
+        self.dispatcher = dispatcher
 
     def is_empty(self):
         return len(self.table) == 0
@@ -582,7 +595,7 @@
                 entry = self.build_funcentry(funcname, calllist)
                 entry.register_valid_types(typesnum)
                 return entry
-            else:
+            elif dispatcher.anychance(typesprefix):
                 flatline = []
                 for num1, t1 in enumerate(lst):
                     item = compress(typesprefix + (t1,), typesnum + (num1,))
@@ -592,6 +605,8 @@
                 else:
                     array = indexarray
                 return array.insert_subarray(flatline)
+            else:
+                return 0
 
         master_index = compress((), ())
 


From arigo at codespeak.net  Thu May 11 14:25:50 2006
From: arigo at codespeak.net (arigo at codespeak.net)
Date: Thu, 11 May 2006 14:25:50 +0200 (CEST)
Subject: [pypy-svn] r27072 - pypy/dist/pypy/objspace/std
Message-ID: <20060511122550.C85AE10082@code0.codespeak.net>

Author: arigo
Date: Thu May 11 14:25:49 2006
New Revision: 27072

Modified:
   pypy/dist/pypy/objspace/std/multimethod.py
Log:
Fixed the multimethod code.  It's still quite slower to
setup, and also slower at run-time on top of CPython.


Modified: pypy/dist/pypy/objspace/std/multimethod.py
==============================================================================
--- pypy/dist/pypy/objspace/std/multimethod.py	(original)
+++ pypy/dist/pypy/objspace/std/multimethod.py	Thu May 11 14:25:49 2006
@@ -362,10 +362,38 @@
         # is there any chance that a list of types starting with typesprefix
         # could lead to a successful dispatch?
         if self._revcache is None:
-            # quick hack!
-            installer = InstallerVersion1(self.multimethod, 'X',
-                                          self.list_of_typeorders)
-            self._revcache = dict.fromkeys(installer.subtree_cache)
+
+            def build_tree(types_so_far, dispatch_node):
+                non_empty = False
+                typeorder = self.list_of_typeorders[len(types_so_far)]
+                for next_type in typeorder:
+                    if build_single_method(typeorder, types_so_far, next_type,
+                                           dispatch_node):
+                        non_empty = True
+                if non_empty:
+                    self._revcache[types_so_far] = True
+                return non_empty
+
+            def build_single_method(typeorder, types_so_far, next_type,
+                                    dispatch_node):
+                order = typeorder[next_type]
+                things_to_call = False
+                for type, conversion in order:
+                    if type not in dispatch_node:
+                        # there is no possible completion of
+                        # types_so_far+[type] that could lead to a
+                        # registered function.
+                        continue
+                    match = dispatch_node[type]
+                    if isinstance(match, dict):
+                        if build_tree(types_so_far+(next_type,), match):
+                            things_to_call = True
+                    elif match:
+                        things_to_call = True
+                return things_to_call
+
+            self._revcache = {}
+            build_tree((), self.multimethod.dispatch_tree)
         return tuple(typesprefix) in self._revcache
 
 
@@ -595,7 +623,7 @@
                 entry = self.build_funcentry(funcname, calllist)
                 entry.register_valid_types(typesnum)
                 return entry
-            elif dispatcher.anychance(typesprefix):
+            elif self.dispatcher.anychance(typesprefix):
                 flatline = []
                 for num1, t1 in enumerate(lst):
                     item = compress(typesprefix + (t1,), typesnum + (num1,))


From arigo at codespeak.net  Thu May 11 15:04:47 2006
From: arigo at codespeak.net (arigo at codespeak.net)
Date: Thu, 11 May 2006 15:04:47 +0200 (CEST)
Subject: [pypy-svn] r27075 - pypy/dist/pypy/module/_pickle_support
Message-ID: <20060511130447.079B51008D@code0.codespeak.net>

Author: arigo
Date: Thu May 11 15:04:46 2006
New Revision: 27075

Modified:
   pypy/dist/pypy/module/_pickle_support/maker.py
Log:
Make PyPy annotatable again.


Modified: pypy/dist/pypy/module/_pickle_support/maker.py
==============================================================================
--- pypy/dist/pypy/module/_pickle_support/maker.py	(original)
+++ pypy/dist/pypy/module/_pickle_support/maker.py	Thu May 11 15:04:46 2006
@@ -37,6 +37,7 @@
 
 #XXX this does not work yet
 def dictiter_new(space, w_dictitertype, __args__):
+    raise Exception('No dictiter_new (pickle support) yet')
     print "dictiter_new here 1)", space, w_dictitertype
     #w_type = space.gettypeobject(dictiter_typedef)
     #print "dictiter_new here 2)", w_type
@@ -53,7 +54,7 @@
 
 #XXX this doesn't work either
 def seqiter_new(space, w_seqitertype, __args__):
-    raise 'No seqiter_new (pickle support) yet'
+    raise Exception('No seqiter_new (pickle support) yet')
     print "seqiter_new here 1)", space, __args__
     w_type = space.gettypeobject(seqiter_typedef)
     print "seqiter_new here 2)", w_type


From antocuni at codespeak.net  Thu May 11 15:16:29 2006
From: antocuni at codespeak.net (antocuni at codespeak.net)
Date: Thu, 11 May 2006 15:16:29 +0200 (CEST)
Subject: [pypy-svn] r27077 - in pypy/dist/pypy/rpython: . lltypesystem
	memory/test ootypesystem test
Message-ID: <20060511131629.B66A010082@code0.codespeak.net>

Author: antocuni
Date: Thu May 11 15:16:26 2006
New Revision: 27077

Modified:
   pypy/dist/pypy/rpython/lltypesystem/rstr.py
   pypy/dist/pypy/rpython/memory/test/test_llinterpsim.py
   pypy/dist/pypy/rpython/ootypesystem/rstr.py
   pypy/dist/pypy/rpython/rstr.py
   pypy/dist/pypy/rpython/test/test_llinterp.py
   pypy/dist/pypy/rpython/test/test_rdict.py
   pypy/dist/pypy/rpython/test/test_rstr.py
Log:
rstr has been refactored: most code belonging to lltypesystem has been
moved from rpython/rstr.py to rpython/lltypesystem/rstr.py.

The low level helpers are collected togheter as staticmethods of the
LLHelpers class. lltypesystem.StringRepr has an 'll' attribute that
contains that class : this way AbstractStringRepr & Co. can reference
them without the needing of a separate StringRepr attribute for each
helper, as happens in rlist.py.



Modified: pypy/dist/pypy/rpython/lltypesystem/rstr.py
==============================================================================
--- pypy/dist/pypy/rpython/lltypesystem/rstr.py	(original)
+++ pypy/dist/pypy/rpython/lltypesystem/rstr.py	Thu May 11 15:16:26 2006
@@ -1,20 +1,40 @@
 from weakref import WeakValueDictionary
-from pypy.rpython.rstr import AbstractStringRepr, char_repr, STR, AbstractStringIteratorRepr, \
-        ll_strconcat, do_stringformat, ll_strhash
-from pypy.rpython.lltypesystem.lltype import malloc, GcStruct, Ptr, nullptr, Signed
+from pypy.annotation.pairtype import pairtype
+from pypy.rpython.robject import PyObjRepr, pyobj_repr
+from pypy.rpython.rarithmetic import _hash_string
+from pypy.rpython.rmodel import inputconst, IntegerRepr
+from pypy.rpython.rstr import AbstractStringRepr, char_repr, AbstractStringIteratorRepr
+from pypy.rpython import rint
+from pypy.rpython.lltypesystem.lltype import \
+     GcStruct, Signed, Array, Char, Ptr, malloc, \
+     Bool, Void, GcArray, nullptr, pyobjectptr
+
+
+
+# ____________________________________________________________
+#
+#  Concrete implementation of RPython strings:
+#
+#    struct str {
+#        hash: Signed
+#        chars: array of Char
+#    }
+
+STR = GcStruct('rpy_string', ('hash',  Signed),
+                             ('chars', Array(Char, hints={'immutable': True,
+                                                          'isrpystring': True})))
+SIGNED_ARRAY = GcArray(Signed)
 
 CONST_STR_CACHE = WeakValueDictionary()
 
+
 class StringRepr(AbstractStringRepr):
 
     lowleveltype = Ptr(STR)
 
     def __init__(self, *args):
         AbstractStringRepr.__init__(self, *args)
-        self.ll_strip = ll_strip
-        self.ll_upper = ll_upper
-        self.ll_lower = ll_lower
-        self.ll_join = ll_join
+        self.ll = LLHelpers
 
     def convert_const(self, value):
         if value is None:
@@ -28,7 +48,7 @@
             p = malloc(STR, len(value))
             for i in range(len(value)):
                 p.chars[i] = value[i]
-            ll_strhash(p)   # precompute the hash
+            self.ll.ll_strhash(p)   # precompute the hash
             CONST_STR_CACHE[value] = p
             return p
 
@@ -42,88 +62,235 @@
             return True     # for CharRepr/UniCharRepr subclasses,
                             # where NULL is always valid: it is chr(0)
 
-def ll_strip(s, ch, left, right):
-    s_len = len(s.chars)
-    if s_len == 0:
-        return emptystr
-    lpos = 0
-    rpos = s_len - 1
-    if left:
-        while lpos < rpos and s.chars[lpos] == ch:
-            lpos += 1
-    if right:
-        while lpos < rpos and s.chars[rpos] == ch:
-            rpos -= 1
-    r_len = rpos - lpos + 1
-    result = malloc(STR, r_len)
-    i = 0
-    j = lpos
-    while i < r_len:
-        result.chars[i] = s.chars[j]
-        i += 1
-        j += 1
-    return result
+# TODO: move it to a better place
+import types
+class StaticMethods(type):
+    """
+    Metaclass that turn all methods into staticmethods.
+    """
+    def __new__(cls, cls_name, bases, cls_dict):
+        for key, value in cls_dict.iteritems():
+            if isinstance(value, types.FunctionType):
+                cls_dict[key] = staticmethod(value)
+        return type.__new__(cls, cls_name, bases, cls_dict)
+
+
+
+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])
+        string_repr = llops.rtyper.type_system.rstr.string_repr
+        v_result = llops.convertvar(v_result, string_repr, r_to)
+        return v_result
+
+class __extend__(pairtype(StringRepr, PyObjRepr)):
+    def convert_from_to((r_from, r_to), v, llops):
+        string_repr = llops.rtyper.type_system.rstr.string_repr
+        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)
+        # xxx put in table        
+        return llops.gencapicall('PyString_FromLLCharArrayAndSize',
+                                 [v_chars, v_size],
+                                 resulttype=pyobj_repr,
+                                 _callable= lambda chars, sz: pyobjectptr(''.join(chars)))
+
+
+
+# ____________________________________________________________
+#
+#  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.
+#
+
+class LLHelpers:
+    __metaclass__ = StaticMethods
+
+    def ll_char_isspace(ch):
+        c = ord(ch) 
+        return c == 32 or (c <= 13 and c >= 9)   # c in (9, 10, 11, 12, 13, 32)
+
+    def ll_char_isdigit(ch):
+        c = ord(ch)
+        return c <= 57 and c >= 48
+
+    def ll_char_isalpha(ch):
+        c = ord(ch)
+        if c >= 97:
+            return c <= 122
+        else:
+            return 65 <= c <= 90
 
-def ll_upper(s):
-    s_chars = s.chars
-    s_len = len(s_chars)
-    if s_len == 0:
-        return emptystr
-    i = 0
-    result = malloc(STR, s_len)
-    while i < s_len:
-        ch = s_chars[i]
-        if 'a' <= ch <= 'z':
-            ch = chr(ord(ch) - 32)
-        result.chars[i] = ch
-        i += 1
-    return result
+    def ll_char_isalnum(ch):
+        c = ord(ch)
+        if c >= 65:
+            if c >= 97:
+                return c <= 122
+            else:
+                return c <= 90
+        else:
+            return 48 <= c <= 57
 
-def ll_lower(s):
-    s_chars = s.chars
-    s_len = len(s_chars)
-    if s_len == 0:
-        return emptystr
-    i = 0
-    result = malloc(STR, s_len)
-    while i < s_len:
-        ch = s_chars[i]
-        if 'A' <= ch <= 'Z':
-            ch = chr(ord(ch) + 32)
-        result.chars[i] = ch
-        i += 1
-    return result
+    def ll_char_isupper(ch):
+        c = ord(ch)
+        return 65 <= c <= 90
+
+    def ll_char_islower(ch):   
+        c = ord(ch)
+        return 97 <= c <= 122
 
-def ll_join(s, length, items):
-    s_chars = s.chars
-    s_len = len(s_chars)
-    num_items = length
-    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:
+    def ll_char_mul(ch, times):
+        newstr = malloc(STR, times)
         j = 0
-        while j < s_len:
-            res_chars[res_index] = s_chars[j]
+        while j < times:
+            newstr.chars[j] = ch
             j += 1
-            res_index += 1
+        return newstr
+
+    def ll_char_hash(ch):
+        return ord(ch)
+
+    def ll_unichar_hash(ch):
+        return ord(ch)
 
+    def ll_strlen(s):
+        return len(s.chars)
+
+    def ll_stritem_nonneg(s, i):
+        return s.chars[i]
+
+    def ll_stritem_nonneg_checked(s, i):
+        if i >= len(s.chars):
+            raise IndexError
+        return s.chars[i]
+
+    def ll_stritem(s, i):
+        if i < 0:
+            i += len(s.chars)
+        return s.chars[i]
+
+    def ll_stritem_checked(s, i):
+        if i < 0:
+            i += len(s.chars)
+        if i >= len(s.chars) or i < 0:
+            raise IndexError
+        return s.chars[i]
+
+    def ll_str_is_true(s):
+        # check if a string is True, allowing for None
+        return bool(s) and len(s.chars) != 0
+
+    def ll_chr2str(ch):
+        s = malloc(STR, 1)
+        s.chars[0] = ch
+        return s
+
+    def ll_strhash(s):
+        # unlike CPython, there is no reason to avoid to return -1
+        # but our malloc initializes the memory to zero, so we use zero as the
+        # special non-computed-yet value.
+        x = s.hash
+        if x == 0:
+            x = _hash_string(s.chars)
+            s.hash = x
+        return x
+
+    def ll_strfasthash(s):
+        return s.hash     # assumes that the hash is already computed
+
+    def ll_strconcat(s1, s2):
+        len1 = len(s1.chars)
+        len2 = len(s2.chars)
+        newstr = malloc(STR, len1 + len2)
+        j = 0
+        while j < len1:
+            newstr.chars[j] = s1.chars[j]
+            j += 1
+        i = 0
+        while i < len2:
+            newstr.chars[j] = s2.chars[i]
+            i += 1
+            j += 1
+        return newstr
+
+    def ll_strip(s, ch, left, right):
+        s_len = len(s.chars)
+        if s_len == 0:
+            return emptystr
+        lpos = 0
+        rpos = s_len - 1
+        if left:
+            while lpos < rpos and s.chars[lpos] == ch:
+                lpos += 1
+        if right:
+            while lpos < rpos and s.chars[rpos] == ch:
+                rpos -= 1
+        r_len = rpos - lpos + 1
+        result = malloc(STR, r_len)
+        i = 0
+        j = lpos
+        while i < r_len:
+            result.chars[i] = s.chars[j]
+            i += 1
+            j += 1
+        return result
+
+    def ll_upper(s):
+        s_chars = s.chars
+        s_len = len(s_chars)
+        if s_len == 0:
+            return emptystr
+        i = 0
+        result = malloc(STR, s_len)
+        while i < s_len:
+            ch = s_chars[i]
+            if 'a' <= ch <= 'z':
+                ch = chr(ord(ch) - 32)
+            result.chars[i] = ch
+            i += 1
+        return result
+
+    def ll_lower(s):
+        s_chars = s.chars
+        s_len = len(s_chars)
+        if s_len == 0:
+            return emptystr
+        i = 0
+        result = malloc(STR, s_len)
+        while i < s_len:
+            ch = s_chars[i]
+            if 'A' <= ch <= 'Z':
+                ch = chr(ord(ch) + 32)
+            result.chars[i] = ch
+            i += 1
+        return result
+
+    def ll_join(s, length, items):
+        s_chars = s.chars
+        s_len = len(s_chars)
+        num_items = length
+        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
@@ -132,15 +299,450 @@
             j += 1
             res_index += 1
         i += 1
-    return result
+        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
+
+    def ll_strcmp(s1, s2):
+        if not s1 and not s2:
+            return True
+        if not s1 or not s2:
+            return False
+        chars1 = s1.chars
+        chars2 = s2.chars
+        len1 = len(chars1)
+        len2 = len(chars2)
 
-char_repr.ll_strip = ll_strip
-char_repr.ll_upper = ll_upper
-char_repr.ll_lower = ll_lower
-char_repr.ll_join = ll_join
+        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):
+        if s1 == s2:       # also if both are NULLs
+            return True
+        if not s1 or not s2:
+            return False
+        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
 
-string_repr = StringRepr()
+        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
+
+    def ll_find_char(s, ch, start, end):
+        i = start
+        while i < end:
+            if s.chars[i] == ch:
+                return i
+            i += 1
+        return -1
+
+    def ll_rfind_char(s, ch, start, end):
+        i = end
+        while i > start:
+            i -= 1
+            if s.chars[i] == ch:
+                return i
+        return -1
+
+    @classmethod
+    def ll_find(cls, s1, s2, start, end):
+        """Knuth Morris Prath algorithm for substring match"""
+        len2 = len(s2.chars)
+        if len2 == 1:
+            return cls.ll_find_char(s1, s2.chars[0], start, end)
+        if len2 == 0:
+            return start
+        # Construct the array of possible restarting positions
+        # T = Array_of_ints [-1..len2]
+        # T[-1] = -1 s2.chars[-1] is supposed to be unequal to everything else
+        T = malloc( SIGNED_ARRAY, len2 )
+        T[0] = 0
+        i = 1
+        j = 0
+        while i0:
+                j = T[j-1]
+            else:
+                T[i] = 0
+                i += 1
+                j = 0
+
+        # Now the find algorithm
+        i = 0
+        m = start
+        while m+i1:
+                j = T[j-2]
+            else:
+                T[i] = 1
+                i += 1
+                j = 1
+
+        # Now the find algorithm
+        i = 1
+        m = end
+        while m-i>=start:
+            if s1.chars[m-i]==s2.chars[len2-i]:
+                if i==len2:
+                    return m-i
+                i += 1
+            else:
+                # mismatch, go back to the last possible starting pos
+                if i==1:
+                    m -= 1
+                else:
+                    e = T[i-2]
+                    m = m - i + e
+                    i = e
+        return -1
+
+    def ll_join_strs(length, items):
+        num_items = length
+        itemslen = 0
+        i = 0
+        while i < num_items:
+            itemslen += len(items[i].chars)
+            i += 1
+        result = malloc(STR, itemslen)
+        res_chars = result.chars
+        res_index = 0
+        i = 0
+        while i < num_items:
+            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
+
+    def ll_join_chars(length, chars):
+        num_chars = length
+        result = malloc(STR, num_chars)
+        res_chars = result.chars
+        i = 0
+        while i < num_chars:
+            res_chars[i] = chars[i]
+            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
+        if stop > len(s1.chars):
+            stop = len(s1.chars)
+        newstr = malloc(STR, stop - start)
+        j = 0
+        while start < stop:
+            newstr.chars[j] = s1.chars[start]
+            start += 1
+            j += 1
+        return newstr
 
+    def ll_stringslice_minusone(s1):
+        newlen = len(s1.chars) - 1
+        assert newlen >= 0
+        newstr = malloc(STR, newlen)
+        j = 0
+        while j < newlen:
+            newstr.chars[j] = s1.chars[j]
+            j += 1
+        return newstr
+
+    def ll_split_chr(LIST, s, c):
+        chars = s.chars
+        strlen = len(chars)
+        count = 1
+        i = 0
+        while i < strlen:
+            if chars[i] == c:
+                count += 1
+            i += 1
+        res = LIST.ll_newlist(count)
+        items = res.ll_items()
+        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
+
+    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)
+        i = 0
+        while i < strlen:
+            if chars[i] == c:
+                return True
+            i += 1
+        return False
+
+    def ll_int(s, base):
+        if not 2 <= base <= 36:
+            raise ValueError
+        chars = s.chars
+        strlen = len(chars)
+        i = 0
+        #XXX: only space is allowed as white space for now
+        while i < strlen and chars[i] == ' ':
+            i += 1
+        if not i < strlen:
+            raise ValueError
+        #check sign
+        sign = 1
+        if chars[i] == '-':
+            sign = -1
+            i += 1
+        elif chars[i] == '+':
+            i += 1;
+        #now get digits
+        val = 0
+        while i < strlen:
+            c = ord(chars[i])
+            if ord('a') <= c <= ord('z'):
+                digit = c - ord('a') + 10
+            elif ord('A') <= c <= ord('Z'):
+                digit = c - ord('A') + 10
+            elif ord('0') <= c <= ord('9'):
+                digit = c - ord('0')
+            else:
+                break
+            if digit >= base:
+                break
+            val = val * base + digit
+            i += 1
+        #skip trailing whitespace
+        while i < strlen and chars[i] == ' ':
+            i += 1
+        if not i == strlen:
+            raise ValueError
+        return sign * val
+
+    @classmethod
+    def do_stringformat(cls, hop, sourcevarsrepr):
+        s_str = hop.args_s[0]
+        assert s_str.is_constant()
+        s = s_str.const
+        things = cls.parse_fmt_string(s)
+        size = inputconst(Signed, len(things)) # could be unsigned?
+        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)
+
+        InstanceRepr = hop.rtyper.type_system.rclass.InstanceRepr
+        for i, thing in enumerate(things):
+            if isinstance(thing, tuple):
+                code = thing[0]
+                vitem, r_arg = argsiter.next()
+                if not hasattr(r_arg, 'll_str'):
+                    raise TyperError("ll_str unsupported for: %r" % r_arg)
+                if code == 's' or (code == 'r' and isinstance(r_arg, InstanceRepr)):
+                    vchunk = hop.gendirectcall(r_arg.ll_str, vitem)
+                elif code == 'd':
+                    assert isinstance(r_arg, IntegerRepr)
+                    vchunk = hop.gendirectcall(r_arg.ll_str, vitem)
+                elif code == 'f':
+                    #assert isinstance(r_arg, FloatRepr)
+                    vchunk = hop.gendirectcall(r_arg.ll_str, vitem)
+                elif code == 'x':
+                    assert isinstance(r_arg, IntegerRepr)
+                    vchunk = hop.gendirectcall(rint.ll_int2hex, vitem,
+                                               inputconst(Bool, False))
+                elif code == 'o':
+                    assert isinstance(r_arg, IntegerRepr)
+                    vchunk = hop.gendirectcall(rint.ll_int2oct, vitem,
+                                               inputconst(Bool, False))
+                else:
+                    raise TyperError, "%%%s is not RPython" % (code, )
+            else:
+                from pypy.rpython.lltypesystem.rstr import string_repr
+                vchunk = inputconst(string_repr, thing)
+            i = inputconst(Signed, i)
+            hop.genop('setarrayitem', [vtemp, i, vchunk])
+
+        hop.exception_cannot_occur()   # to ignore the ZeroDivisionError of '%'
+        return hop.gendirectcall(cls.ll_join_strs, size, vtemp)
+
+    def parse_fmt_string(fmt):
+        # we support x, d, s, f, [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 = ''
+                if f not in 'xdosrf':
+                    raise TyperError("Unsupported formatting specifier: %r in %r" % (f, fmt))
+
+                r.append((f,))
+            else:
+                curstr += c
+        if curstr:
+            r.append(curstr)
+        return r
+
+
+# TODO: make the public interface of the rstr module cleaner
+ll_strconcat = LLHelpers.ll_strconcat
+ll_join = LLHelpers.ll_join
+do_stringformat = LLHelpers.do_stringformat
+
+
+
+char_repr.ll = LLHelpers
+string_repr = StringRepr()
 emptystr = string_repr.convert_const("")
 
 

Modified: pypy/dist/pypy/rpython/memory/test/test_llinterpsim.py
==============================================================================
--- pypy/dist/pypy/rpython/memory/test/test_llinterpsim.py	(original)
+++ pypy/dist/pypy/rpython/memory/test/test_llinterpsim.py	Thu May 11 15:16:26 2006
@@ -4,7 +4,7 @@
 from pypy.rpython.rtyper import RPythonTyper
 from pypy.rpython.llinterp import LLInterpreter, LLException,log
 from pypy.rpython.rint import signed_repr
-from pypy.rpython import rstr
+from pypy.rpython.lltypesystem import rstr
 from pypy.annotation.model import lltype_to_annotation
 from pypy.rpython.rarithmetic import r_uint, ovfcheck
 from pypy.rpython.memory.lltypesimulation import pyobjectptr

Modified: pypy/dist/pypy/rpython/ootypesystem/rstr.py
==============================================================================
--- pypy/dist/pypy/rpython/ootypesystem/rstr.py	(original)
+++ pypy/dist/pypy/rpython/ootypesystem/rstr.py	Thu May 11 15:16:26 2006
@@ -1,4 +1,4 @@
-from pypy.rpython.rstr import AbstractStringRepr, STR, AbstractStringIteratorRepr
+from pypy.rpython.rstr import AbstractStringRepr, AbstractStringIteratorRepr
 from pypy.rpython.lltypesystem.lltype import Ptr
 from pypy.rpython.ootypesystem.ootype import Signed, Record, String, make_string
 

Modified: pypy/dist/pypy/rpython/rstr.py
==============================================================================
--- pypy/dist/pypy/rpython/rstr.py	(original)
+++ pypy/dist/pypy/rpython/rstr.py	Thu May 11 15:16:26 2006
@@ -4,8 +4,6 @@
 from pypy.rpython.error import TyperError
 from pypy.rpython.rmodel import IntegerRepr, IteratorRepr
 from pypy.rpython.rmodel import AbstractStringRepr, CharRepr, inputconst, UniCharRepr
-from pypy.rpython.rarithmetic import _hash_string
-from pypy.rpython.robject import PyObjRepr, pyobj_repr
 from pypy.rpython.lltypesystem.rtuple import TupleRepr # XXX type system!
 from pypy.rpython import rint
 from pypy.rpython.lltypesystem.rslice import SliceRepr # XXX type system!
@@ -15,22 +13,6 @@
      GcStruct, Signed, Array, Char, Ptr, malloc, \
      Bool, Void, GcArray, nullptr, pyobjectptr
 
-
-# ____________________________________________________________
-#
-#  Concrete implementation of RPython strings:
-#
-#    struct str {
-#        hash: Signed
-#        chars: array of Char
-#    }
-
-STR = GcStruct('rpy_string', ('hash',  Signed),
-                             ('chars', Array(Char, hints={'immutable': True,
-                                                          'isrpystring': True})))
-SIGNED_ARRAY = GcArray(Signed)
-
-
 class __extend__(annmodel.SomeString):
     def rtyper_makerepr(self, rtyper):
         return rtyper.type_system.rstr.string_repr
@@ -49,7 +31,6 @@
     def rtyper_makekey(self):
         return self.__class__,
 
-CONST_STR_CACHE = WeakValueDictionary()
 #string_repr = StringRepr()
 char_repr   = CharRepr()
 unichar_repr = UniCharRepr()
@@ -57,74 +38,58 @@
 
 class __extend__(AbstractStringRepr):
 
-    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:
-            return CONST_STR_CACHE[value]
-        except KeyError:
-            p = malloc(STR, len(value))
-            for i in range(len(value)):
-                p.chars[i] = value[i]
-            ll_strhash(p)   # precompute the hash
-            CONST_STR_CACHE[value] = p
-            return p
-
     def get_ll_eq_function(self):
-        return ll_streq
+        return self.ll.ll_streq
 
     def get_ll_hash_function(self):
-        return ll_strhash
+        return self.ll.ll_strhash
 
     def get_ll_fasthash_function(self):
-        return ll_strfasthash
+        return self.ll.ll_strfasthash
 
-    def rtype_len(_, hop):
+    def rtype_len(self, hop):
         string_repr = hop.rtyper.type_system.rstr.string_repr
         v_str, = hop.inputargs(string_repr)
-        return hop.gendirectcall(ll_strlen, v_str)
+        return hop.gendirectcall(self.ll.ll_strlen, v_str)
 
     def rtype_is_true(self, hop):
         s_str = hop.args_s[0]
         if s_str.can_be_None:
             string_repr = hop.rtyper.type_system.rstr.string_repr
             v_str, = hop.inputargs(string_repr)
-            return hop.gendirectcall(ll_str_is_true, v_str)
+            return hop.gendirectcall(self.ll.ll_str_is_true, v_str)
         else:
             # defaults to checking the length
             return super(AbstractStringRepr, self).rtype_is_true(hop)
 
-    def rtype_ord(_, hop):
+    def rtype_ord(self, hop):
         string_repr = hop.rtyper.type_system.rstr.string_repr
         v_str, = hop.inputargs(string_repr)
         c_zero = inputconst(Signed, 0)
-        v_chr = hop.gendirectcall(ll_stritem_nonneg, v_str, c_zero)
+        v_chr = hop.gendirectcall(self.ll.ll_stritem_nonneg, v_str, c_zero)
         return hop.genop('cast_char_to_int', [v_chr], resulttype=Signed)
 
-    def rtype_method_startswith(_, hop):
+    def rtype_method_startswith(self, hop):
         string_repr = hop.rtyper.type_system.rstr.string_repr
         v_str, v_value = hop.inputargs(string_repr, string_repr)
         hop.exception_cannot_occur()
-        return hop.gendirectcall(ll_startswith, v_str, v_value)
+        return hop.gendirectcall(self.ll.ll_startswith, v_str, v_value)
 
-    def rtype_method_endswith(_, hop):
+    def rtype_method_endswith(self, hop):
         string_repr = hop.rtyper.type_system.rstr.string_repr
         v_str, v_value = hop.inputargs(string_repr, string_repr)
         hop.exception_cannot_occur()
-        return hop.gendirectcall(ll_endswith, v_str, v_value)
+        return hop.gendirectcall(self.ll.ll_endswith, v_str, v_value)
 
-    def rtype_method_find(_, hop, reverse=False):
+    def rtype_method_find(self, hop, reverse=False):
         string_repr = hop.rtyper.type_system.rstr.string_repr
         v_str = hop.inputarg(string_repr, arg=0)
         if hop.args_r[1] == char_repr:
             v_value = hop.inputarg(char_repr, arg=1)
-            llfn = reverse and ll_rfind_char or ll_find_char
+            llfn = reverse and self.ll.ll_rfind_char or self.ll.ll_find_char
         else:
             v_value = hop.inputarg(string_repr, arg=1)
-            llfn = reverse and ll_rfind or ll_find
+            llfn = reverse and self.ll.ll_rfind or self.ll.ll_find
         if hop.nb_args > 2:
             v_start = hop.inputarg(Signed, arg=2)
             if not hop.args_s[2].nonneg:
@@ -136,7 +101,7 @@
             if not hop.args_s[2].nonneg:
                 raise TyperError("str.find() end must be proven non-negative")
         else:
-            v_end = hop.gendirectcall(ll_strlen, v_str)
+            v_end = hop.gendirectcall(self.ll.ll_strlen, v_str)
         hop.exception_cannot_occur()
         return hop.gendirectcall(llfn, v_str, v_value, v_start, v_end)
 
@@ -149,7 +114,7 @@
         v_char = hop.inputarg(char_repr, arg=1)
         v_left = hop.inputconst(Bool, left)
         v_right = hop.inputconst(Bool, right)
-        return hop.gendirectcall(self.ll_strip, v_str, v_char, v_left, v_right)
+        return hop.gendirectcall(self.ll.ll_strip, v_str, v_char, v_left, v_right)
 
     def rtype_method_lstrip(self, hop):
         return self.rtype_method_strip(hop, left=True, right=False)
@@ -161,13 +126,13 @@
         string_repr = hop.rtyper.type_system.rstr.string_repr
         v_str, = hop.inputargs(string_repr)
         hop.exception_cannot_occur()
-        return hop.gendirectcall(self.ll_upper, v_str)
+        return hop.gendirectcall(self.ll.ll_upper, v_str)
         
     def rtype_method_lower(self, hop):
         string_repr = hop.rtyper.type_system.rstr.string_repr
         v_str, = hop.inputargs(string_repr)
         hop.exception_cannot_occur()
-        return hop.gendirectcall(self.ll_lower, v_str)
+        return hop.gendirectcall(self.ll.ll_lower, v_str)
         
     def rtype_method_join(self, hop):
         hop.exception_cannot_occur()
@@ -184,224 +149,149 @@
                        
         if hop.args_s[0].is_constant() and hop.args_s[0].const == '':
             if r_lst.item_repr == string_repr:
-                llfn = ll_join_strs
+                llfn = self.ll.ll_join_strs
             elif r_lst.item_repr == char_repr:
-                llfn = ll_join_chars
+                llfn = self.ll.ll_join_chars
             else:
                 raise TyperError("''.join() of non-string list: %r" % r_lst)
             return hop.gendirectcall(llfn, v_length, v_items)
         else:
             if r_lst.item_repr == string_repr:
-                llfn = self.ll_join
+                llfn = self.ll.ll_join
             else:
                 raise TyperError("sep.join() of non-string list: %r" % r_lst)
             return hop.gendirectcall(llfn, v_str, v_length, v_items)
 
-    def rtype_method_split(_, hop):
+    def rtype_method_split(self, hop):
         string_repr = hop.rtyper.type_system.rstr.string_repr
         v_str, v_chr = hop.inputargs(string_repr, char_repr)
         cLIST = hop.inputconst(Void, hop.r_result.lowleveltype.TO)
         hop.exception_cannot_occur()
-        return hop.gendirectcall(ll_split_chr, cLIST, v_str, v_chr)
+        return hop.gendirectcall(self.ll.ll_split_chr, cLIST, v_str, v_chr)
 
-    def rtype_method_replace(_, hop):
+    def rtype_method_replace(self, hop):
         if not (hop.args_r[1] == char_repr and hop.args_r[2] == char_repr):
             raise TyperError, 'replace only works for char args'
         string_repr = hop.rtyper.type_system.rstr.string_repr
         v_str, v_c1, v_c2 = hop.inputargs(string_repr, char_repr, char_repr)
         hop.exception_cannot_occur()
-        return hop.gendirectcall(ll_replace_chr_chr, v_str, v_c1, v_c2)
+        return hop.gendirectcall(self.ll.ll_replace_chr_chr, v_str, v_c1, v_c2)
 
-    def rtype_int(_, hop):
+    def rtype_int(self, hop):
         hop.has_implicit_exception(ValueError)   # record that we know about it
         string_repr = hop.rtyper.type_system.rstr.string_repr
         if hop.nb_args == 1:
             v_str, = hop.inputargs(string_repr)
             c_base = inputconst(Signed, 10)
             hop.exception_is_here()
-            return hop.gendirectcall(ll_int, v_str, c_base)
+            return hop.gendirectcall(self.ll.ll_int, v_str, c_base)
         if not hop.args_r[1] == rint.signed_repr:
             raise TyperError, 'base needs to be an int'
         v_str, v_base= hop.inputargs(string_repr, rint.signed_repr)
         hop.exception_is_here()
-        return hop.gendirectcall(ll_int, v_str, v_base)
+        return hop.gendirectcall(self.ll.ll_int, v_str, v_base)
 
     def ll_str(self, s):
         return s
 
 class __extend__(pairtype(AbstractStringRepr, IntegerRepr)):
-    def rtype_getitem(_, hop):
+    def rtype_getitem((r_str, r_int), hop):
         string_repr = hop.rtyper.type_system.rstr.string_repr
         v_str, v_index = hop.inputargs(string_repr, Signed)
         if hop.has_implicit_exception(IndexError):
             if hop.args_s[1].nonneg:
-                llfn = ll_stritem_nonneg_checked
+                llfn = r_str.ll.ll_stritem_nonneg_checked
             else:
-                llfn = ll_stritem_checked
+                llfn = r_str.ll.ll_stritem_checked
         else:
             if hop.args_s[1].nonneg:
-                llfn = ll_stritem_nonneg
+                llfn = r_str.ll.ll_stritem_nonneg
             else:
-                llfn = ll_stritem
+                llfn = r_str.ll.ll_stritem
         hop.exception_is_here()
         return hop.gendirectcall(llfn, v_str, v_index)
 
-    def rtype_mod(_, hop):
-        rstr = hop.rtyper.type_system.rstr
-        return rstr.do_stringformat(hop, [(hop.args_v[1], hop.args_r[1])])
+    def rtype_mod((r_str, r_int), hop):
+        return r_str.ll.do_stringformat(hop, [(hop.args_v[1], hop.args_r[1])])
 
 
 class __extend__(pairtype(AbstractStringRepr, SliceRepr)):
 
-    def rtype_getitem((_, r_slic), hop):
+    def rtype_getitem((r_str, r_slic), hop):
         string_repr = hop.rtyper.type_system.rstr.string_repr
         if r_slic == startonly_slice_repr:
             v_str, v_start = hop.inputargs(string_repr, startonly_slice_repr)
-            return hop.gendirectcall(ll_stringslice_startonly, v_str, v_start)
+            return hop.gendirectcall(r_str.ll.ll_stringslice_startonly, v_str, v_start)
         if r_slic == startstop_slice_repr:
             v_str, v_slice = hop.inputargs(string_repr, startstop_slice_repr)
-            return hop.gendirectcall(ll_stringslice, v_str, v_slice)
+            return hop.gendirectcall(r_str.ll.ll_stringslice, v_str, v_slice)
         if r_slic == minusone_slice_repr:
             v_str, v_ignored = hop.inputargs(string_repr, minusone_slice_repr)
-            return hop.gendirectcall(ll_stringslice_minusone, v_str)
+            return hop.gendirectcall(r_str.ll.ll_stringslice_minusone, v_str)
         raise TyperError(r_slic)
 
 
 class __extend__(pairtype(AbstractStringRepr, AbstractStringRepr)):
-    def rtype_add(_, hop):
+    def rtype_add((r_str1, r_str2), hop):
         string_repr = hop.rtyper.type_system.rstr.string_repr
         v_str1, v_str2 = hop.inputargs(string_repr, string_repr)
-        return hop.gendirectcall(ll_strconcat, v_str1, v_str2)
+        return hop.gendirectcall(r_str1.ll.ll_strconcat, v_str1, v_str2)
     rtype_inplace_add = rtype_add
 
-    def rtype_eq(_, hop):
+    def rtype_eq((r_str1, r_str2), hop):
         string_repr = hop.rtyper.type_system.rstr.string_repr
         v_str1, v_str2 = hop.inputargs(string_repr, string_repr)
-        return hop.gendirectcall(ll_streq, v_str1, v_str2)
+        return hop.gendirectcall(r_str1.ll.ll_streq, v_str1, v_str2)
     
-    def rtype_ne(_, hop):
+    def rtype_ne((r_str1, r_str2), hop):
         string_repr = hop.rtyper.type_system.rstr.string_repr
         v_str1, v_str2 = hop.inputargs(string_repr, string_repr)
-        vres = hop.gendirectcall(ll_streq, v_str1, v_str2)
+        vres = hop.gendirectcall(r_str1.ll.ll_streq, v_str1, v_str2)
         return hop.genop('bool_not', [vres], resulttype=Bool)
 
-    def rtype_lt(_, hop):
+    def rtype_lt((r_str1, r_str2), hop):
         string_repr = hop.rtyper.type_system.rstr.string_repr
         v_str1, v_str2 = hop.inputargs(string_repr, string_repr)
-        vres = hop.gendirectcall(ll_strcmp, v_str1, v_str2)
+        vres = hop.gendirectcall(r_str1.ll.ll_strcmp, v_str1, v_str2)
         return hop.genop('int_lt', [vres, hop.inputconst(Signed, 0)],
                          resulttype=Bool)
 
-    def rtype_le(_, hop):
+    def rtype_le((r_str1, r_str2), hop):
         string_repr = hop.rtyper.type_system.rstr.string_repr
         v_str1, v_str2 = hop.inputargs(string_repr, string_repr)
-        vres = hop.gendirectcall(ll_strcmp, v_str1, v_str2)
+        vres = hop.gendirectcall(r_str1.ll.ll_strcmp, v_str1, v_str2)
         return hop.genop('int_le', [vres, hop.inputconst(Signed, 0)],
                          resulttype=Bool)
 
-    def rtype_ge(_, hop):
+    def rtype_ge((r_str1, r_str2), hop):
         string_repr = hop.rtyper.type_system.rstr.string_repr
         v_str1, v_str2 = hop.inputargs(string_repr, string_repr)
-        vres = hop.gendirectcall(ll_strcmp, v_str1, v_str2)
+        vres = hop.gendirectcall(r_str1.ll.ll_strcmp, v_str1, v_str2)
         return hop.genop('int_ge', [vres, hop.inputconst(Signed, 0)],
                          resulttype=Bool)
 
-    def rtype_gt(_, hop):
+    def rtype_gt((r_str1, r_str2), hop):
         string_repr = hop.rtyper.type_system.rstr.string_repr
         v_str1, v_str2 = hop.inputargs(string_repr, string_repr)
-        vres = hop.gendirectcall(ll_strcmp, v_str1, v_str2)
+        vres = hop.gendirectcall(r_str1.ll.ll_strcmp, v_str1, v_str2)
         return hop.genop('int_gt', [vres, hop.inputconst(Signed, 0)],
                          resulttype=Bool)
 
-    def rtype_mod(_, hop):
-        rstr = hop.rtyper.type_system.rstr
-        return rstr.do_stringformat(hop, [(hop.args_v[1], hop.args_r[1])])
+    def rtype_mod((r_str1, r_str2), hop):
+        return r_str1.ll.do_stringformat(hop, [(hop.args_v[1], hop.args_r[1])])
 
 class __extend__(pairtype(AbstractStringRepr, CharRepr)):
-    def rtype_contains(_, hop):
+    def rtype_contains((r_str, r_chr), hop):
         string_repr = hop.rtyper.type_system.rstr.string_repr
         v_str, v_chr = hop.inputargs(string_repr, char_repr)
-        return hop.gendirectcall(ll_contains, v_str, v_chr)
+        return hop.gendirectcall(r_str.ll.ll_contains, v_str, v_chr)
     
-def parse_fmt_string(fmt):
-    # we support x, d, s, f, [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 = ''
-            if f not in 'xdosrf':
-                raise TyperError("Unsupported formatting specifier: %r in %r" % (f, fmt))
-
-            r.append((f,))
-        else:
-            curstr += c
-    if curstr:
-        r.append(curstr)
-    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(Signed, len(things)) # could be unsigned?
-    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)
-    
-    InstanceRepr = hop.rtyper.type_system.rclass.InstanceRepr
-    for i, thing in enumerate(things):
-        if isinstance(thing, tuple):
-            code = thing[0]
-            vitem, r_arg = argsiter.next()
-            if not hasattr(r_arg, 'll_str'):
-                raise TyperError("ll_str unsupported for: %r" % r_arg)
-            if code == 's' or (code == 'r' and isinstance(r_arg, InstanceRepr)):
-                vchunk = hop.gendirectcall(r_arg.ll_str, vitem)
-            elif code == 'd':
-                assert isinstance(r_arg, IntegerRepr)
-                vchunk = hop.gendirectcall(r_arg.ll_str, vitem)
-            elif code == 'f':
-                #assert isinstance(r_arg, FloatRepr)
-                vchunk = hop.gendirectcall(r_arg.ll_str, vitem)
-            elif code == 'x':
-                assert isinstance(r_arg, IntegerRepr)
-                vchunk = hop.gendirectcall(rint.ll_int2hex, vitem,
-                                           inputconst(Bool, False))
-            elif code == 'o':
-                assert isinstance(r_arg, IntegerRepr)
-                vchunk = hop.gendirectcall(rint.ll_int2oct, vitem,
-                                           inputconst(Bool, False))
-            else:
-                raise TyperError, "%%%s is not RPython" % (code, )
-        else:
-            from pypy.rpython.lltypesystem.rstr import string_repr
-            vchunk = inputconst(string_repr, thing)
-        i = inputconst(Signed, i)
-        hop.genop('setarrayitem', [vtemp, i, vchunk])
-
-    hop.exception_cannot_occur()   # to ignore the ZeroDivisionError of '%'
-    return hop.gendirectcall(ll_join_strs, size, vtemp)
     
 
 class __extend__(pairtype(AbstractStringRepr, TupleRepr)):
-    def rtype_mod(_, hop):
+    def rtype_mod((r_str, r_tuple), hop):
         r_tuple = hop.args_r[1]
         v_tuple = hop.args_v[1]
 
@@ -412,8 +302,7 @@
                               resulttype=r_arg)
             sourcevars.append((vitem, r_arg))
 
-        rstr = hop.rtyper.type_system.rstr
-        return rstr.do_stringformat(hop, sourcevars)
+        return r_str.ll.do_stringformat(hop, sourcevars)
                 
 
 class __extend__(CharRepr):
@@ -427,12 +316,12 @@
         return None 
 
     def get_ll_hash_function(self):
-        return ll_char_hash
+        return self.ll.ll_char_hash
 
     get_ll_fasthash_function = get_ll_hash_function
 
     def ll_str(self, ch):
-        return ll_chr2str(ch)
+        return self.ll.ll_chr2str(ch)
 
     def rtype_len(_, hop):
         return hop.inputconst(Signed, 1)
@@ -451,29 +340,29 @@
         return hop.gendirectcall(llfn, vlist[0])
 
     def rtype_method_isspace(self, hop):
-        return self._rtype_method_isxxx(ll_char_isspace, hop)
+        return self._rtype_method_isxxx(self.ll.ll_char_isspace, hop)
     def rtype_method_isdigit(self, hop):
-        return self._rtype_method_isxxx(ll_char_isdigit, hop)
+        return self._rtype_method_isxxx(self.ll.ll_char_isdigit, hop)
     def rtype_method_isalpha(self, hop):
-        return self._rtype_method_isxxx(ll_char_isalpha, hop)
+        return self._rtype_method_isxxx(self.ll.ll_char_isalpha, hop)
     def rtype_method_isalnum(self, hop):
-        return self._rtype_method_isxxx(ll_char_isalnum, hop)
+        return self._rtype_method_isxxx(self.ll.ll_char_isalnum, hop)
     def rtype_method_isupper(self, hop):
-        return self._rtype_method_isxxx(ll_char_isupper, hop)
+        return self._rtype_method_isxxx(self.ll.ll_char_isupper, hop)
     def rtype_method_islower(self, hop):
-        return self._rtype_method_isxxx(ll_char_islower, hop)
+        return self._rtype_method_isxxx(self.ll.ll_char_islower, hop)
 
 class __extend__(pairtype(CharRepr, IntegerRepr)):
     
-    def rtype_mul(_, hop):
+    def rtype_mul((r_chr, r_int), hop):
         v_char, v_int = hop.inputargs(char_repr, Signed)
-        return hop.gendirectcall(ll_char_mul, v_char, v_int)
+        return hop.gendirectcall(r_chr.ll.ll_char_mul, v_char, v_int)
     rtype_inplace_mul = rtype_mul
 
 class __extend__(pairtype(IntegerRepr, CharRepr)):
-    def rtype_mul(_, hop):
+    def rtype_mul((r_int, r_chr), hop):
         v_int, v_char = hop.inputargs(Signed, char_repr)
-        return hop.gendirectcall(ll_char_mul, v_char, v_int)
+        return hop.gendirectcall(r_chr.ll.ll_char_mul, v_char, v_int)
     rtype_inplace_mul = rtype_mul
 
 class __extend__(pairtype(CharRepr, CharRepr)):
@@ -501,7 +390,7 @@
         return None 
 
     def get_ll_hash_function(self):
-        return ll_unichar_hash
+        return self.ll.ll_unichar_hash
 
     get_ll_fasthash_function = get_ll_hash_function
 
@@ -539,7 +428,7 @@
     def convert_from_to((r_from, r_to), v, llops):
         string_repr = llops.rtyper.type_system.rstr.string_repr
         if r_from == char_repr and r_to == string_repr:
-            return llops.gendirectcall(ll_chr2str, v)
+            return llops.gendirectcall(r_from.ll.ll_chr2str, v)
         return NotImplemented
 
 class __extend__(pairtype(AbstractStringRepr, CharRepr)):
@@ -547,489 +436,10 @@
         string_repr = llops.rtyper.type_system.rstr.string_repr
         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 llops.gendirectcall(r_from.ll.ll_stritem_nonneg, v, c_zero)
         return NotImplemented
 
-class __extend__(pairtype(PyObjRepr, AbstractStringRepr)):
-    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])
-        string_repr = llops.rtyper.type_system.rstr.string_repr
-        v_result = llops.convertvar(v_result, string_repr, r_to)
-        return v_result
 
-class __extend__(pairtype(AbstractStringRepr, PyObjRepr)):
-    def convert_from_to((r_from, r_to), v, llops):
-        string_repr = llops.rtyper.type_system.rstr.string_repr
-        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)
-        # xxx put in table        
-        return llops.gencapicall('PyString_FromLLCharArrayAndSize',
-                                 [v_chars, v_size],
-                                 resulttype=pyobj_repr,
-                                 _callable= lambda chars, sz: pyobjectptr(''.join(chars)))
-
-# ____________________________________________________________
-#
-#  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):
-    c = ord(ch) 
-    return c == 32 or (c <= 13 and c >= 9)   # c in (9, 10, 11, 12, 13, 32)
-
-def ll_char_isdigit(ch):
-    c = ord(ch)
-    return c <= 57 and c >= 48
-
-def ll_char_isalpha(ch):
-    c = ord(ch)
-    if c >= 97:
-        return c <= 122
-    else:
-        return 65 <= c <= 90
-
-def ll_char_isalnum(ch):
-    c = ord(ch)
-    if c >= 65:
-        if c >= 97:
-            return c <= 122
-        else:
-            return c <= 90
-    else:
-        return 48 <= c <= 57
-
-def ll_char_isupper(ch):
-    c = ord(ch)
-    return 65 <= c <= 90
-
-def ll_char_islower(ch):   
-    c = ord(ch)
-    return 97 <= c <= 122
-
-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_char_hash(ch):
-    return ord(ch)
-
-def ll_unichar_hash(ch):
-    return ord(ch)
-
-def ll_strlen(s):
-    return len(s.chars)
-
-def ll_stritem_nonneg(s, i):
-    return s.chars[i]
-
-def ll_stritem_nonneg_checked(s, i):
-    if i >= len(s.chars):
-        raise IndexError
-    return s.chars[i]
-
-def ll_stritem(s, i):
-    if i < 0:
-        i += len(s.chars)
-    return s.chars[i]
-
-def ll_stritem_checked(s, i):
-    if i < 0:
-        i += len(s.chars)
-    if i >= len(s.chars) or i < 0:
-        raise IndexError
-    return s.chars[i]
-
-def ll_str_is_true(s):
-    # check if a string is True, allowing for None
-    return bool(s) and len(s.chars) != 0
-
-def ll_chr2str(ch):
-    s = malloc(STR, 1)
-    s.chars[0] = ch
-    return s
-
-def ll_strhash(s):
-    # unlike CPython, there is no reason to avoid to return -1
-    # but our malloc initializes the memory to zero, so we use zero as the
-    # special non-computed-yet value.
-    x = s.hash
-    if x == 0:
-        x = _hash_string(s.chars)
-        s.hash = x
-    return x
-
-def ll_strfasthash(s):
-    return s.hash     # assumes that the hash is already computed
-
-def ll_strconcat(s1, s2):
-    len1 = len(s1.chars)
-    len2 = len(s2.chars)
-    newstr = malloc(STR, len1 + len2)
-    j = 0
-    while j < len1:
-        newstr.chars[j] = s1.chars[j]
-        j += 1
-    i = 0
-    while i < len2:
-        newstr.chars[j] = s2.chars[i]
-        i += 1
-        j += 1
-    return newstr
-
-def ll_strcmp(s1, s2):
-    if not s1 and not s2:
-        return True
-    if not s1 or not s2:
-        return False
-    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):
-    if s1 == s2:       # also if both are NULLs
-        return True
-    if not s1 or not s2:
-        return False
-    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
-
-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
-
-def ll_find_char(s, ch, start, end):
-    i = start
-    while i < end:
-        if s.chars[i] == ch:
-            return i
-        i += 1
-    return -1
-
-def ll_rfind_char(s, ch, start, end):
-    i = end
-    while i > start:
-        i -= 1
-        if s.chars[i] == ch:
-            return i
-    return -1
-
-def ll_find(s1, s2, start, end):
-    """Knuth Morris Prath algorithm for substring match"""
-    len2 = len(s2.chars)
-    if len2 == 1:
-        return ll_find_char(s1, s2.chars[0], start, end)
-    if len2 == 0:
-        return start
-    # Construct the array of possible restarting positions
-    # T = Array_of_ints [-1..len2]
-    # T[-1] = -1 s2.chars[-1] is supposed to be unequal to everything else
-    T = malloc( SIGNED_ARRAY, len2 )
-    T[0] = 0
-    i = 1
-    j = 0
-    while i0:
-            j = T[j-1]
-        else:
-            T[i] = 0
-            i += 1
-            j = 0
-
-    # Now the find algorithm
-    i = 0
-    m = start
-    while m+i1:
-            j = T[j-2]
-        else:
-            T[i] = 1
-            i += 1
-            j = 1
-
-    # Now the find algorithm
-    i = 1
-    m = end
-    while m-i>=start:
-        if s1.chars[m-i]==s2.chars[len2-i]:
-            if i==len2:
-                return m-i
-            i += 1
-        else:
-            # mismatch, go back to the last possible starting pos
-            if i==1:
-                m -= 1
-            else:
-                e = T[i-2]
-                m = m - i + e
-                i = e
-    return -1
-
-def ll_join_strs(length, items):
-    num_items = length
-    itemslen = 0
-    i = 0
-    while i < num_items:
-        itemslen += len(items[i].chars)
-        i += 1
-    result = malloc(STR, itemslen)
-    res_chars = result.chars
-    res_index = 0
-    i = 0
-    while i < num_items:
-        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
-
-def ll_join_chars(length, chars):
-    num_chars = length
-    result = malloc(STR, num_chars)
-    res_chars = result.chars
-    i = 0
-    while i < num_chars:
-        res_chars[i] = chars[i]
-        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
-    if stop > len(s1.chars):
-        stop = len(s1.chars)
-    newstr = malloc(STR, stop - start)
-    j = 0
-    while start < stop:
-        newstr.chars[j] = s1.chars[start]
-        start += 1
-        j += 1
-    return newstr
-
-def ll_stringslice_minusone(s1):
-    newlen = len(s1.chars) - 1
-    assert newlen >= 0
-    newstr = malloc(STR, newlen)
-    j = 0
-    while j < newlen:
-        newstr.chars[j] = s1.chars[j]
-        j += 1
-    return newstr
-
-def ll_split_chr(LIST, s, c):
-    chars = s.chars
-    strlen = len(chars)
-    count = 1
-    i = 0
-    while i < strlen:
-        if chars[i] == c:
-            count += 1
-        i += 1
-    res = LIST.ll_newlist(count)
-    items = res.ll_items()
-    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
-
-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)
-    i = 0
-    while i < strlen:
-        if chars[i] == c:
-            return True
-        i += 1
-    return False
-
-def ll_int(s, base):
-    if not 2 <= base <= 36:
-        raise ValueError
-    chars = s.chars
-    strlen = len(chars)
-    i = 0
-    #XXX: only space is allowed as white space for now
-    while i < strlen and chars[i] == ' ':
-        i += 1
-    if not i < strlen:
-        raise ValueError
-    #check sign
-    sign = 1
-    if chars[i] == '-':
-        sign = -1
-        i += 1
-    elif chars[i] == '+':
-        i += 1;
-    #now get digits
-    val = 0
-    while i < strlen:
-        c = ord(chars[i])
-        if ord('a') <= c <= ord('z'):
-            digit = c - ord('a') + 10
-        elif ord('A') <= c <= ord('Z'):
-            digit = c - ord('A') + 10
-        elif ord('0') <= c <= ord('9'):
-            digit = c - ord('0')
-        else:
-            break
-        if digit >= base:
-            break
-        val = val * base + digit
-        i += 1
-    #skip trailing whitespace
-    while i < strlen and chars[i] == ' ':
-        i += 1
-    if not i == strlen:
-        raise ValueError
-    return sign * val
 
 # ____________________________________________________________
 #

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	Thu May 11 15:16:26 2006
@@ -6,7 +6,7 @@
 from pypy.rpython.rmodel import inputconst
 from pypy.translator.translator import TranslationContext
 from pypy.rpython.rint import signed_repr
-from pypy.rpython import rstr
+from pypy.rpython.lltypesystem import rstr
 from pypy.annotation import model as annmodel
 from pypy.annotation.model import lltype_to_annotation
 from pypy.rpython.rarithmetic import r_uint, ovfcheck

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 May 11 15:16:26 2006
@@ -1,8 +1,8 @@
 from pypy.translator.translator import TranslationContext
 from pypy.rpython.lltypesystem import lltype 
 from pypy.rpython.test.test_llinterp import interpret, interpret_raises
-from pypy.rpython import rstr, rint
-from pypy.rpython.lltypesystem import rdict
+from pypy.rpython import rint
+from pypy.rpython.lltypesystem import rdict, rstr
 
 import py
 py.log.setconsumer("rtyper", py.log.STDOUT)
@@ -98,7 +98,7 @@
         p = lltype.malloc(rstr.STR, len(value))
         for i in range(len(value)):
             p.chars[i] = value[i]
-        return rstr.ll_strhash(p) 
+        return rstr.LLHelpers.ll_strhash(p) 
     
     def func(c1, c2): 
         c1 = chr(c1) 

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 May 11 15:16:26 2006
@@ -1,6 +1,6 @@
 import random
 from pypy.rpython.lltypesystem.lltype import *
-from pypy.rpython.rstr import parse_fmt_string, ll_find, ll_rfind, STR
+from pypy.rpython.lltypesystem.rstr import LLHelpers, STR
 from pypy.rpython.rtyper import RPythonTyper, TyperError
 from pypy.rpython.test.test_llinterp import interpret, interpret_raises
 from pypy.rpython.llinterp import LLException
@@ -17,9 +17,9 @@
         s1 = ''.join([random.choice("ab") for i in range(n1)])
         n2 = random.randint(0, 5)
         s2 = ''.join([random.choice("ab") for i in range(n2)])
-        res = ll_find(llstr(s1), llstr(s2), 0, n1)
+        res = LLHelpers.ll_find(llstr(s1), llstr(s2), 0, n1)
         assert res == s1.find(s2)
-        res = ll_rfind(llstr(s1), llstr(s2), 0, n1)
+        res = LLHelpers.ll_rfind(llstr(s1), llstr(s2), 0, n1)
         assert res == s1.rfind(s2)
 
 def test_simple():
@@ -326,9 +326,9 @@
             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"]
+    assert LLHelpers.parse_fmt_string('a') == ['a']
+    assert LLHelpers.parse_fmt_string('%s') == [('s',)]
+    assert LLHelpers.parse_fmt_string("name '%s' is not defined") == ["name '", ("s",), "' is not defined"]
 
 def test_strformat():
     def percentS(s):


From arigo at codespeak.net  Thu May 11 15:42:18 2006
From: arigo at codespeak.net (arigo at codespeak.net)
Date: Thu, 11 May 2006 15:42:18 +0200 (CEST)
Subject: [pypy-svn] r27078 - pypy/dist/pypy/objspace/std
Message-ID: <20060511134218.CDAE11008F@code0.codespeak.net>

Author: arigo
Date: Thu May 11 15:42:17 2006
New Revision: 27078

Modified:
   pypy/dist/pypy/objspace/std/multimethod.py
Log:
Fixed broken multimethod version 2.


Modified: pypy/dist/pypy/objspace/std/multimethod.py
==============================================================================
--- pypy/dist/pypy/objspace/std/multimethod.py	(original)
+++ pypy/dist/pypy/objspace/std/multimethod.py	Thu May 11 15:42:17 2006
@@ -463,6 +463,18 @@
         self.indexarray.ensure_length(len(next_array.items))
 
 
+def invent_name(miniglobals, obj):
+    if isinstance(obj, str):
+        return obj
+    name = obj.__name__
+    n = 1
+    while name in miniglobals:
+        n += 1
+        name = '%s%d' % (obj.__name__, n)
+    miniglobals[name] = obj
+    return name
+
+
 class FuncEntry(object):
 
     def __init__(self, bodylines, miniglobals, fallback):
@@ -483,7 +495,7 @@
             return self._function
         name = min(self.possiblenames)   # pick a random one, but consistently
         self.compress_typechecks(mrdtable)
-        checklines = self.generate_typechecks(fnargs[nbargs_before:], mrdtable)
+        checklines = self.generate_typechecks(fnargs[nbargs_before:])
         if checklines == ['pass']:
             body = self.body
         else:
@@ -496,15 +508,15 @@
         self._function = self.miniglobals[name]
         return self._function
 
-    def register_valid_types(self, typenums):
+    def register_valid_types(self, types):
         node = self.typetree
-        for n in typenums[:-1]:
+        for t1 in types[:-1]:
             if node is True:
                 return
-            node = node.setdefault(n, {})
+            node = node.setdefault(t1, {})
         if node is True:
             return
-        node[typenums[-1]] = True
+        node[types[-1]] = True
 
     def no_typecheck(self):
         self.typetree = True
@@ -526,7 +538,7 @@
         if full(self.typetree):
             self.typetree = True
 
-    def generate_typechecks(self, args, mrdtable):
+    def generate_typechecks(self, args):
         def generate(node, level=0):
             indent = '    '*level
             if node is True:
@@ -537,14 +549,15 @@
                 return
             keyword = 'if'
             for key, subnode in node.items():
-                result.append('%s%s %s == %d:' % (indent, keyword,
-                                                  typeidexprs[level], key))
+                typename = invent_name(self.miniglobals, key)
+                result.append('%s%s isinstance(%s, %s):' % (indent, keyword,
+                                                            args[level],
+                                                            typename))
                 generate(subnode, level+1)
                 keyword = 'elif'
             result.append('%selse:' % (indent,))
             result.append('%s    raise FailedToImplement' % (indent,))
 
-        typeidexprs = ['%s.%s' % (arg, mrdtable.attrname) for arg in args]
         result = []
         generate(self.typetree)
         return result
@@ -557,7 +570,7 @@
 
     def __init__(self, multimethod, prefix, list_of_typeorders,
                  baked_perform_call=True, base_typeorder=None):
-        #print 'InstallerVersion2:', prefix
+        print 'InstallerVersion2:', prefix
         self.multimethod = multimethod
         self.prefix = prefix
         self.list_of_typeorders = list_of_typeorders
@@ -621,7 +634,7 @@
                     funcname.append(t1.__name__)
                 funcname = '_'.join(funcname)
                 entry = self.build_funcentry(funcname, calllist)
-                entry.register_valid_types(typesnum)
+                entry.register_valid_types(typesprefix)
                 return entry
             elif self.dispatcher.anychance(typesprefix):
                 flatline = []
@@ -680,20 +693,9 @@
             return self.fnargs, expr, entry.miniglobals, entry.fallback
 
     def build_funcentry(self, funcname, calllist, **extranames):
-        def invent_name(obj):
-            if isinstance(obj, str):
-                return obj
-            name = obj.__name__
-            n = 1
-            while name in miniglobals:
-                n += 1
-                name = '%s%d' % (obj.__name__, n)
-            miniglobals[name] = obj
-            return name
-
         def expr(v):
             if isinstance(v, Call):
-                return '%s(%s)' % (invent_name(v.function),
+                return '%s(%s)' % (invent_name(miniglobals, v.function),
                                    ', '.join([expr(w) for w in v.arguments]))
             else:
                 return v


From arigo at codespeak.net  Thu May 11 16:48:48 2006
From: arigo at codespeak.net (arigo at codespeak.net)
Date: Thu, 11 May 2006 16:48:48 +0200 (CEST)
Subject: [pypy-svn] r27080 - pypy/dist/pypy/module/stackless
Message-ID: <20060511144848.A0A4510082@code0.codespeak.net>

Author: arigo
Date: Thu May 11 16:48:47 2006
New Revision: 27080

Modified:
   pypy/dist/pypy/module/stackless/__init__.py
Log:
A change probably checked in by accident.


Modified: pypy/dist/pypy/module/stackless/__init__.py
==============================================================================
--- pypy/dist/pypy/module/stackless/__init__.py	(original)
+++ pypy/dist/pypy/module/stackless/__init__.py	Thu May 11 16:48:47 2006
@@ -10,7 +10,7 @@
     }
 
     interpleveldefs = {
-        #'tasklet'    : 'interp_stackless.tasklet',
+        'tasklet'    : 'interp_stackless.tasklet',
         'coroutine'  : 'coroutine.AppCoroutine',
     }
 


From arigo at codespeak.net  Thu May 11 16:54:03 2006
From: arigo at codespeak.net (arigo at codespeak.net)
Date: Thu, 11 May 2006 16:54:03 +0200 (CEST)
Subject: [pypy-svn] r27081 - in pypy/dist/pypy: objspace/std translator/goal
Message-ID: <20060511145403.10EB310082@code0.codespeak.net>

Author: arigo
Date: Thu May 11 16:54:01 2006
New Revision: 27081

Modified:
   pypy/dist/pypy/objspace/std/multimethod.py
   pypy/dist/pypy/translator/goal/targetpypystandalone.py
Log:
So far, multimethod.py uses the InstallerVersion1 by default
because it is much faster both to initialize and run on top of CPython.
The InstallerVersion2 is optimized for making a translator-friendly
structure.  So we patch it in-place from targetpypystandalone...
That's temporary, hopefully.


Modified: pypy/dist/pypy/objspace/std/multimethod.py
==============================================================================
--- pypy/dist/pypy/objspace/std/multimethod.py	(original)
+++ pypy/dist/pypy/objspace/std/multimethod.py	Thu May 11 16:54:01 2006
@@ -570,7 +570,7 @@
 
     def __init__(self, multimethod, prefix, list_of_typeorders,
                  baked_perform_call=True, base_typeorder=None):
-        print 'InstallerVersion2:', prefix
+        #print 'InstallerVersion2:', prefix
         self.multimethod = multimethod
         self.prefix = prefix
         self.list_of_typeorders = list_of_typeorders
@@ -727,4 +727,4 @@
 # ____________________________________________________________
 # Selection of the version to use
 
-Installer = InstallerVersion1
+Installer = InstallerVersion1   # modified by translate.py targetpypystandalone

Modified: pypy/dist/pypy/translator/goal/targetpypystandalone.py
==============================================================================
--- pypy/dist/pypy/translator/goal/targetpypystandalone.py	(original)
+++ pypy/dist/pypy/translator/goal/targetpypystandalone.py	Thu May 11 16:54:01 2006
@@ -1,4 +1,12 @@
 import os, sys
+
+# as of revision 27081, multimethod.py uses the InstallerVersion1 by default
+# because it is much faster both to initialize and run on top of CPython.
+# The InstallerVersion2 is optimized for making a translator-friendly
+# structure.  So we patch here...
+from pypy.objspace.std import multimethod
+multimethod.Installer = multimethod.InstallerVersion2
+
 from pypy.objspace.std.objspace import StdObjSpace
 # XXX from pypy.annotation.model import *
 # since we are execfile()'ed this would pull some
@@ -9,10 +17,6 @@
 from pypy.interpreter.error import OperationError
 from pypy.translator.goal.ann_override import PyPyAnnotatorPolicy
 
-# WARNING: this requires the annotator.
-# There is no easy way to build all caches manually,
-# but the annotator can do it for us for free.
-
 try:
     this_dir = os.path.dirname(__file__)
 except NameError:


From pedronis at codespeak.net  Thu May 11 17:46:43 2006
From: pedronis at codespeak.net (pedronis at codespeak.net)
Date: Thu, 11 May 2006 17:46:43 +0200 (CEST)
Subject: [pypy-svn] r27086 - in pypy/dist/pypy/annotation: . test
Message-ID: <20060511154643.5490310082@code0.codespeak.net>

Author: pedronis
Date: Thu May 11 17:46:41 2006
New Revision: 27086

Modified:
   pypy/dist/pypy/annotation/binaryop.py
   pypy/dist/pypy/annotation/test/test_annrpython.py
Log:
unbreak rshift annotation



Modified: pypy/dist/pypy/annotation/binaryop.py
==============================================================================
--- pypy/dist/pypy/annotation/binaryop.py	(original)
+++ pypy/dist/pypy/annotation/binaryop.py	Thu May 11 17:46:41 2006
@@ -254,10 +254,12 @@
     def lshift((int1, int2)):
         return SomeInteger(knowntype=int1.knowntype)
 
-    lshift.can_only_throw = [ValueError]
-    rshift = lshift
     lshift_ovf = _clone(lshift, [ValueError, OverflowError])
 
+    def rshift((int1, int2)):
+        return SomeInteger(nonneg=int1.nonneg, knowntype=int1.knowntype)
+    rshift.can_only_throw = [ValueError]
+
     def pow((int1, int2), obj3):
         knowntype = rarithmetic.compute_restype(int1.knowntype, int2.knowntype)
         return SomeInteger(nonneg = int1.nonneg,
@@ -301,9 +303,11 @@
         return SomeInteger()
 
     lshift.can_only_throw = [ValueError]
-    rshift = lshift
     lshift_ovf = _clone(lshift, [ValueError, OverflowError])
 
+    def rshift((int1, int2)):
+        return SomeInteger(nonneg=True)
+    rshift.can_only_throw = [ValueError]
 
 class __extend__(pairtype(SomeBool, SomeBool)):
 

Modified: pypy/dist/pypy/annotation/test/test_annrpython.py
==============================================================================
--- pypy/dist/pypy/annotation/test/test_annrpython.py	(original)
+++ pypy/dist/pypy/annotation/test/test_annrpython.py	Thu May 11 17:46:41 2006
@@ -2161,7 +2161,15 @@
             assert isinstance(s, annmodel.SomeInteger)
             assert s.knowntype == inttype
             assert s.unsigned == (inttype(-1) > 0)
-        
+
+    def test_annotate_rshift(self):
+        def f(x):
+            return x >> 2
+        a = self.RPythonAnnotator()
+        s = a.build_types(f, [annmodel.SomeInteger(nonneg=True)])
+        assert isinstance(s, annmodel.SomeInteger)
+        assert s.nonneg
+
 
 
 def g(n):


From antocuni at codespeak.net  Thu May 11 17:49:08 2006
From: antocuni at codespeak.net (antocuni at codespeak.net)
Date: Thu, 11 May 2006 17:49:08 +0200 (CEST)
Subject: [pypy-svn] r27087 - pypy/dist/pypy/rpython/lltypesystem
Message-ID: <20060511154908.2503510082@code0.codespeak.net>

Author: antocuni
Date: Thu May 11 17:49:01 2006
New Revision: 27087

Modified:
   pypy/dist/pypy/rpython/lltypesystem/rstr.py
Log:
Added missing ll attribute to unichar_repr



Modified: pypy/dist/pypy/rpython/lltypesystem/rstr.py
==============================================================================
--- pypy/dist/pypy/rpython/lltypesystem/rstr.py	(original)
+++ pypy/dist/pypy/rpython/lltypesystem/rstr.py	Thu May 11 17:49:01 2006
@@ -3,7 +3,7 @@
 from pypy.rpython.robject import PyObjRepr, pyobj_repr
 from pypy.rpython.rarithmetic import _hash_string
 from pypy.rpython.rmodel import inputconst, IntegerRepr
-from pypy.rpython.rstr import AbstractStringRepr, char_repr, AbstractStringIteratorRepr
+from pypy.rpython.rstr import AbstractStringRepr, char_repr, unichar_repr, AbstractStringIteratorRepr
 from pypy.rpython import rint
 from pypy.rpython.lltypesystem.lltype import \
      GcStruct, Signed, Array, Char, Ptr, malloc, \
@@ -739,9 +739,8 @@
 ll_join = LLHelpers.ll_join
 do_stringformat = LLHelpers.do_stringformat
 
-
-
 char_repr.ll = LLHelpers
+unichar_repr.ll = LLHelpers
 string_repr = StringRepr()
 emptystr = string_repr.convert_const("")
 


From ac at codespeak.net  Thu May 11 19:01:02 2006
From: ac at codespeak.net (ac at codespeak.net)
Date: Thu, 11 May 2006 19:01:02 +0200 (CEST)
Subject: [pypy-svn] r27089 - pypy/dist/pypy/rpython
Message-ID: <20060511170102.5B3FB10082@code0.codespeak.net>

Author: ac
Date: Thu May 11 19:01:01 2006
New Revision: 27089

Modified:
   pypy/dist/pypy/rpython/llinterp.py
Log:
Fix typo.

Modified: pypy/dist/pypy/rpython/llinterp.py
==============================================================================
--- pypy/dist/pypy/rpython/llinterp.py	(original)
+++ pypy/dist/pypy/rpython/llinterp.py	Thu May 11 19:01:01 2006
@@ -47,12 +47,12 @@
         # prepare_graphs_and_create_gc might already use the llinterpreter!
         self.gc = None
         self.tracer = None
+        self.frame_class = LLFrame
         if hasattr(heap, "prepare_graphs_and_create_gc"):
             flowgraphs = typer.annotator.translator.graphs
             self.gc = heap.prepare_graphs_and_create_gc(self, flowgraphs)
         if self.TRACING:
             self.tracer = Tracer()
-        self.frame_class = LLFrame
 
     def eval_graph(self, graph, args=()):
         llframe = self.frame_class(graph, args, self)


From pedronis at codespeak.net  Thu May 11 19:42:14 2006
From: pedronis at codespeak.net (pedronis at codespeak.net)
Date: Thu, 11 May 2006 19:42:14 +0200 (CEST)
Subject: [pypy-svn] r27091 - pypy/dist/pypy/module/marshal
Message-ID: <20060511174214.DC5C310087@code0.codespeak.net>

Author: pedronis
Date: Thu May 11 19:42:12 2006
New Revision: 27091

Modified:
   pypy/dist/pypy/module/marshal/interp_marshal.py
Log:
make annotation happy again.



Modified: pypy/dist/pypy/module/marshal/interp_marshal.py
==============================================================================
--- pypy/dist/pypy/module/marshal/interp_marshal.py	(original)
+++ pypy/dist/pypy/module/marshal/interp_marshal.py	Thu May 11 19:42:12 2006
@@ -373,10 +373,11 @@
         b = ord(s[1])
         c = ord(s[2])
         d = ord(s[3])
-        if d & 0x80:
-            self.raise_exc('bad marshal data')
         x = a | (b<<8) | (c<<16) | (d<<24)
-        return x
+        if x >= 0:
+            return x
+        else:
+            self.raise_exc('bad marshal data')
 
     def get_pascal(self):
         lng = ord(self.get1())
@@ -498,7 +499,8 @@
         b = ord(self.bufstr[pos+1])
         c = ord(self.bufstr[pos+2])
         d = ord(self.bufstr[pos+3])
-        if d & 0x80:
-            self.raise_exc('bad marshal data')
         x = a | (b<<8) | (c<<16) | (d<<24)
-        return x
+        if x >= 0:
+            return x
+        else:
+            self.raise_exc('bad marshal data')


From ac at codespeak.net  Thu May 11 20:05:41 2006
From: ac at codespeak.net (ac at codespeak.net)
Date: Thu, 11 May 2006 20:05:41 +0200 (CEST)
Subject: [pypy-svn] r27092 - in pypy/dist/pypy/rpython: . lltypesystem
Message-ID: <20060511180541.5AEBD10087@code0.codespeak.net>

Author: ac
Date: Thu May 11 20:05:40 2006
New Revision: 27092

Modified:
   pypy/dist/pypy/rpython/lltypesystem/rstr.py
   pypy/dist/pypy/rpython/rarithmetic.py
Log:
Python2.3-ify.

Modified: pypy/dist/pypy/rpython/lltypesystem/rstr.py
==============================================================================
--- pypy/dist/pypy/rpython/lltypesystem/rstr.py	(original)
+++ pypy/dist/pypy/rpython/lltypesystem/rstr.py	Thu May 11 20:05:40 2006
@@ -404,7 +404,6 @@
                 return i
         return -1
 
-    @classmethod
     def ll_find(cls, s1, s2, start, end):
         """Knuth Morris Prath algorithm for substring match"""
         len2 = len(s2.chars)
@@ -448,8 +447,8 @@
                     m = m + i - e
                     i = e
         return -1
+    ll_find = classmethod(ll_find)
 
-    @classmethod
     def ll_rfind(cls, s1, s2, start, end):
         """Reversed version of ll_find()"""
         len2 = len(s2.chars)
@@ -491,6 +490,7 @@
                     m = m - i + e
                     i = e
         return -1
+    ll_rfind = classmethod(ll_rfind)
 
     def ll_join_strs(length, items):
         num_items = length
@@ -657,7 +657,6 @@
             raise ValueError
         return sign * val
 
-    @classmethod
     def do_stringformat(cls, hop, sourcevarsrepr):
         s_str = hop.args_s[0]
         assert s_str.is_constant()
@@ -706,6 +705,7 @@
 
         hop.exception_cannot_occur()   # to ignore the ZeroDivisionError of '%'
         return hop.gendirectcall(cls.ll_join_strs, size, vtemp)
+    do_stringformat = classmethod(do_stringformat)
 
     def parse_fmt_string(fmt):
         # we support x, d, s, f, [r]

Modified: pypy/dist/pypy/rpython/rarithmetic.py
==============================================================================
--- pypy/dist/pypy/rpython/rarithmetic.py	(original)
+++ pypy/dist/pypy/rpython/rarithmetic.py	Thu May 11 20:05:40 2006
@@ -272,7 +272,7 @@
         base_int_type = signed_int
     else:
         base_int_type = unsigned_int
-    mask = (1 << bits) - 1
+    mask = (2 ** bits) - 1
     if name is None:
         raise TypeError('No predefined %sint%d'%(['u', ''][sign], bits))
     int_type = _inttypes[sign, bits] = type(name, (base_int_type,), {'MASK': mask,


From antocuni at codespeak.net  Thu May 11 20:23:17 2006
From: antocuni at codespeak.net (antocuni at codespeak.net)
Date: Thu, 11 May 2006 20:23:17 +0200 (CEST)
Subject: [pypy-svn] r27093 - in pypy/dist/pypy/rpython: . lltypesystem
Message-ID: <20060511182317.526C510087@code0.codespeak.net>

Author: antocuni
Date: Thu May 11 20:23:09 2006
New Revision: 27093

Modified:
   pypy/dist/pypy/rpython/lltypesystem/rstr.py
   pypy/dist/pypy/rpython/rstr.py
Log:
Fixed a robject bug due to rstr refactoring.



Modified: pypy/dist/pypy/rpython/lltypesystem/rstr.py
==============================================================================
--- pypy/dist/pypy/rpython/lltypesystem/rstr.py	(original)
+++ pypy/dist/pypy/rpython/lltypesystem/rstr.py	Thu May 11 20:23:09 2006
@@ -76,34 +76,33 @@
 
 
 
-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])
-        string_repr = llops.rtyper.type_system.rstr.string_repr
-        v_result = llops.convertvar(v_result, string_repr, r_to)
-        return v_result
-
-class __extend__(pairtype(StringRepr, PyObjRepr)):
-    def convert_from_to((r_from, r_to), v, llops):
-        string_repr = llops.rtyper.type_system.rstr.string_repr
-        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)
-        # xxx put in table        
-        return llops.gencapicall('PyString_FromLLCharArrayAndSize',
-                                 [v_chars, v_size],
-                                 resulttype=pyobj_repr,
-                                 _callable= lambda chars, sz: pyobjectptr(''.join(chars)))
+
+def convert_PyObjRepr_StringRepr((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])
+    string_repr = llops.rtyper.type_system.rstr.string_repr
+    v_result = llops.convertvar(v_result, string_repr, r_to)
+    return v_result
+
+def convert_StringRepr_PyObjRepr((r_from, r_to), v, llops):
+    string_repr = llops.rtyper.type_system.rstr.string_repr
+    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)
+    # xxx put in table        
+    return llops.gencapicall('PyString_FromLLCharArrayAndSize',
+                             [v_chars, v_size],
+                             resulttype=pyobj_repr,
+                             _callable= lambda chars, sz: pyobjectptr(''.join(chars)))
 
 
 

Modified: pypy/dist/pypy/rpython/rstr.py
==============================================================================
--- pypy/dist/pypy/rpython/rstr.py	(original)
+++ pypy/dist/pypy/rpython/rstr.py	Thu May 11 20:23:09 2006
@@ -4,6 +4,7 @@
 from pypy.rpython.error import TyperError
 from pypy.rpython.rmodel import IntegerRepr, IteratorRepr
 from pypy.rpython.rmodel import AbstractStringRepr, CharRepr, inputconst, UniCharRepr
+from pypy.rpython.robject import PyObjRepr, pyobj_repr
 from pypy.rpython.lltypesystem.rtuple import TupleRepr # XXX type system!
 from pypy.rpython import rint
 from pypy.rpython.lltypesystem.rslice import SliceRepr # XXX type system!
@@ -439,6 +440,15 @@
             return llops.gendirectcall(r_from.ll.ll_stritem_nonneg, v, c_zero)
         return NotImplemented
 
+class __extend__(pairtype(PyObjRepr, AbstractStringRepr)):
+    def convert_from_to(this_pair, v, llops):
+        rstr = llops.rtyper.type_system.rstr
+        return rstr.convert_PyObjRepr_StringRepr(this_pair, v, llops)
+
+class __extend__(pairtype(AbstractStringRepr, PyObjRepr)):
+    def convert_from_to(this_pair, v, llops):
+        rstr = llops.rtyper.type_system.rstr
+        return rstr.convert_StringRepr_PyObjRepr(this_pair, v, llops)
 
 
 # ____________________________________________________________


From ac at codespeak.net  Thu May 11 20:25:54 2006
From: ac at codespeak.net (ac at codespeak.net)
Date: Thu, 11 May 2006 20:25:54 +0200 (CEST)
Subject: [pypy-svn] r27094 - in pypy/dist/pypy: rpython rpython/lltypesystem
	rpython/rctypes rpython/rctypes/test translator/c
Message-ID: <20060511182554.BE6B010087@code0.codespeak.net>

Author: ac
Date: Thu May 11 20:25:53 2006
New Revision: 27094

Modified:
   pypy/dist/pypy/rpython/llinterp.py
   pypy/dist/pypy/rpython/lltypesystem/lloperation.py
   pypy/dist/pypy/rpython/lltypesystem/lltype.py
   pypy/dist/pypy/rpython/rarithmetic.py
   pypy/dist/pypy/rpython/rctypes/aprimitive.py
   pypy/dist/pypy/rpython/rctypes/rprimitive.py
   pypy/dist/pypy/rpython/rctypes/test/test_rprimitive.py
   pypy/dist/pypy/rpython/rint.py
   pypy/dist/pypy/translator/c/funcgen.py
   pypy/dist/pypy/translator/c/primitive.py
Log:
(pedronis, arre) Support translation of ctypes.c_short (more types to come soon...)


Modified: pypy/dist/pypy/rpython/llinterp.py
==============================================================================
--- pypy/dist/pypy/rpython/llinterp.py	(original)
+++ pypy/dist/pypy/rpython/llinterp.py	Thu May 11 20:25:53 2006
@@ -337,7 +337,8 @@
         # XXX these special cases DO pile up, do something better here
         if operation.opname in ['cast_pointer', 'ooupcast', 'oodowncast',
                                 'cast_adr_to_ptr', 'cast_int_to_ptr',
-                                'cast_opaque_ptr', 'unsafe_call']:
+                                'cast_opaque_ptr', 'unsafe_call',
+                                'cast_primitive']:
             vals.insert(0, operation.result.concretetype)
         try:
             retval = ophandler(*vals)
@@ -593,6 +594,10 @@
         assert isinstance(index, int)
         return lltype.direct_ptradd(obj, index)
 
+    def op_cast_primitive(self, TYPE, value):
+        assert isinstance(lltype.typeOf(value), lltype.Primitive)
+        return lltype.cast_primitive(TYPE, value)
+
     def op_cast_ptr_to_int(self, ptr1):
         assert checkptr(ptr1)
         assert isinstance(lltype.typeOf(ptr1).TO, (lltype.Array, lltype.Struct))

Modified: pypy/dist/pypy/rpython/lltypesystem/lloperation.py
==============================================================================
--- pypy/dist/pypy/rpython/lltypesystem/lloperation.py	(original)
+++ pypy/dist/pypy/rpython/lltypesystem/lloperation.py	Thu May 11 20:25:53 2006
@@ -236,6 +236,7 @@
     'ullong_rshift_val':    LLOp(canfold=True, canraise=(ValueError,)),
     'ullong_xor':           LLOp(canfold=True),
 
+    'cast_primitive':       LLOp(canfold=True),
     'cast_bool_to_int':     LLOp(canfold=True),
     'cast_bool_to_uint':    LLOp(canfold=True),
     'cast_bool_to_float':   LLOp(canfold=True),

Modified: pypy/dist/pypy/rpython/lltypesystem/lltype.py
==============================================================================
--- pypy/dist/pypy/rpython/lltypesystem/lltype.py	(original)
+++ pypy/dist/pypy/rpython/lltypesystem/lltype.py	Thu May 11 20:25:53 2006
@@ -1,6 +1,7 @@
 import py
 from pypy.rpython.rarithmetic import r_int, r_uint, intmask
 from pypy.rpython.rarithmetic import r_ulonglong, r_longlong, base_int
+from pypy.rpython.rarithmetic import normalizedinttype
 from pypy.rpython.objectmodel import Symbolic
 from pypy.tool.uid import Hashable
 from pypy.tool.tls import tlsobject
@@ -491,7 +492,11 @@
         else:
             self._cast = cast
 
-_numbertypes = {int: Number("Signed", int, )}
+    def normalized(self):
+        return build_number(None, normalizedinttype(self._type))
+        
+
+_numbertypes = {int: Number("Signed", int, intmask)}
 _numbertypes[r_int] = _numbertypes[int]
 
 def build_number(name, type):

Modified: pypy/dist/pypy/rpython/rarithmetic.py
==============================================================================
--- pypy/dist/pypy/rpython/rarithmetic.py	(original)
+++ pypy/dist/pypy/rpython/rarithmetic.py	Thu May 11 20:25:53 2006
@@ -93,6 +93,14 @@
         return other_type
     return build_int(None, self_type.SIGNED and other_type.SIGNED, max(self_type.BITS, other_type.BITS))
 
+def normalizedinttype(t):
+    if t is int:
+        return int
+    if t.BITS <= r_int.BITS:
+        return build_int(None, t.SIGNED, r_int.BITS)
+    else:
+        assert t.BITS <= r_longlong.BITS
+        return build_int(None, t.SIGNED, r_longlong.BITS)
 
 class base_int(long):
     """ fake unsigned integer implementation """

Modified: pypy/dist/pypy/rpython/rctypes/aprimitive.py
==============================================================================
--- pypy/dist/pypy/rpython/rctypes/aprimitive.py	(original)
+++ pypy/dist/pypy/rpython/rctypes/aprimitive.py	Thu May 11 20:25:53 2006
@@ -4,13 +4,14 @@
 from pypy.annotation import model as annmodel
 from pypy.rpython.rctypes.implementation import CTypesCallEntry, CTypesObjEntry
 from pypy.rpython.lltypesystem import lltype
+from pypy.rpython.rctypes import rcarithmetic as rcarith
 
 ctypes_annotation_list = {
     c_char:          lltype.Char,
     c_wchar:         lltype.UniChar,
     c_byte:          lltype.Signed,
     c_ubyte:         lltype.Unsigned,
-    c_short:         lltype.Signed,
+    c_short:         rcarith.CShort,
     c_ushort:        lltype.Unsigned,
     c_int:           lltype.Signed,
     c_uint:          lltype.Unsigned,
@@ -22,6 +23,11 @@
     c_double:        lltype.Float,
 }   # nb. platform-dependent duplicate ctypes are removed
 
+def return_lltype(c_type):
+    ll_type = ctypes_annotation_list[c_type]
+    if isinstance(ll_type, lltype.Number):
+        return ll_type.normalized()
+    return ll_type
 
 class CallEntry(CTypesCallEntry):
     "Annotation and rtyping of calls to primitive c_xxx types."
@@ -49,7 +55,7 @@
         return self.get_s_value()
 
     def get_s_value(self):
-        ll_type = ctypes_annotation_list[self.type]
+        ll_type = return_lltype(self.type)
         return annmodel.lltype_to_annotation(ll_type)
 
     s_return_trick = property(get_s_value)

Modified: pypy/dist/pypy/rpython/rctypes/rprimitive.py
==============================================================================
--- pypy/dist/pypy/rpython/rctypes/rprimitive.py	(original)
+++ pypy/dist/pypy/rpython/rctypes/rprimitive.py	Thu May 11 20:25:53 2006
@@ -8,16 +8,27 @@
 
 class PrimitiveRepr(CTypesValueRepr):
 
+    def __init__(self, rtyper, s_ctypesobject, ll_type):
+        CTypesValueRepr.__init__(self, rtyper, s_ctypesobject, ll_type)
+        if isinstance(ll_type, lltype.Number):
+            normalized_lltype = ll_type.normalized()
+        else:
+            normalized_lltype = ll_type
+        self.value_repr = rtyper.getprimitiverepr(ll_type)
+        self.normalized_value_repr = rtyper.getprimitiverepr(normalized_lltype)
+            
     def return_c_data(self, llops, v_c_data):
         """Read out the atomic data from a raw C pointer.
         Used when the data is returned from an operation or C function call.
         """
-        return self.getvalue_from_c_data(llops, v_c_data)
+        v_value = self.getvalue_from_c_data(llops, v_c_data)
+        return self.return_value(llops, v_value)
 
     def return_value(self, llops, v_value):
         # like return_c_data(), but when the input is only the value
         # field instead of the c_data pointer
-        return v_value
+        return llops.convertvar(v_value, self.value_repr,
+                               self.normalized_value_repr)
 
     def rtype_getattr(self, hop):
         s_attr = hop.args_s[1]
@@ -25,7 +36,8 @@
         assert s_attr.const == 'value'
         v_primitive = hop.inputarg(self, 0)
         hop.exception_cannot_occur()
-        return self.getvalue(hop.llops, v_primitive)
+        v_c_data = self.get_c_data(hop.llops, v_primitive)
+        return self.return_c_data(hop.llops, v_c_data)
 
     def rtype_setattr(self, hop):
         s_attr = hop.args_s[1]
@@ -35,6 +47,11 @@
                                                         self.ll_type)
         self.setvalue(hop.llops, v_primitive, v_value)
 
+    def initialize_const(self, p, value):
+        if isinstance(value, self.ctype):
+            value = value.value
+        p.c_data[0] = lltype.cast_primitive(self.ll_type, value)
+
 
 class __extend__(pairtype(IntegerRepr, PrimitiveRepr),
                  pairtype(FloatRepr, PrimitiveRepr),

Modified: pypy/dist/pypy/rpython/rctypes/test/test_rprimitive.py
==============================================================================
--- pypy/dist/pypy/rpython/rctypes/test/test_rprimitive.py	(original)
+++ pypy/dist/pypy/rpython/rctypes/test/test_rprimitive.py	Thu May 11 20:25:53 2006
@@ -12,10 +12,11 @@
 import sys
 from pypy.rpython.test.test_llinterp import interpret
 from pypy.rpython.rarithmetic import r_longlong, r_ulonglong
-
+from pypy.rpython.lltypesystem import lltype
 from ctypes import c_char, c_byte, c_ubyte, c_short, c_ushort, c_int, c_uint
 from ctypes import c_long, c_ulong, c_longlong, c_ulonglong, c_float
 from ctypes import c_double, c_wchar, c_char_p, pointer, sizeof
+from ctypes import Structure
 
 class Test_annotation:
     def test_simple(self):
@@ -114,6 +115,121 @@
         if conftest.option.view:
             t.view()
 
+    def test_annotate_primitive_value(self):
+        def func(x):
+            cs = c_short(x)
+            return cs.value
+        t = TranslationContext()
+        a = t.buildannotator()
+        s = a.build_types(func, [int])
+
+        assert s.knowntype == int
+
+        if conftest.option.view:
+            t.view()
+            
+    def test_annotate_primitive_arrayitem(self):
+        CSA = c_short * 1
+        def func(x):
+            csa = CSA(x)
+            return csa[0]
+        t = TranslationContext()
+        a = t.buildannotator()
+        s = a.build_types(func, [int])
+
+        assert s.knowntype == int
+
+        if conftest.option.view:
+            t.view()
+            
+    def test_annotate_primitive_ptritem(self):
+        def func(x):
+            cs = pointer(c_short(x))
+            return cs[0]
+        t = TranslationContext()
+        a = t.buildannotator()
+        s = a.build_types(func, [int])
+
+        assert s.knowntype == int
+
+        if conftest.option.view:
+            t.view()
+
+    def test_annotate_primitive_structfield(self):
+        class S(Structure):
+            _fields_ = [('cs', c_short)]
+        def func(x):
+            s = S(x)
+            return s.cs
+        t = TranslationContext()
+        a = t.buildannotator()
+        s = a.build_types(func, [int])
+
+        assert s.knowntype == int
+
+        if conftest.option.view:
+            t.view()
+            
+    def test_annotate_set_primitive_value(self):
+        def func(x):
+            cs = c_short()
+            cs.value = x
+            return cs.value
+        t = TranslationContext()
+        a = t.buildannotator()
+        s = a.build_types(func, [int])
+
+        assert s.knowntype == int
+
+        if conftest.option.view:
+            t.view()
+
+    def test_annotate_set_primitive_arrayitem(self):
+        CSA = c_short * 1
+        def func(x):
+            csa = CSA()
+            csa[0] = x
+            return csa[0]
+        t = TranslationContext()
+        a = t.buildannotator()
+        s = a.build_types(func, [int])
+
+        assert s.knowntype == int
+
+        if conftest.option.view:
+            t.view()
+            
+    def test_annotate_set_primitive_ptritem(self):
+        def func(x):
+            cs = pointer(c_short())
+            cs[0] = x
+            return cs[0]
+        t = TranslationContext()
+        a = t.buildannotator()
+        s = a.build_types(func, [int])
+
+        assert s.knowntype == int
+
+        if conftest.option.view:
+            t.view()
+
+    def test_annotate_set_primitive_structfield(self):
+        class S(Structure):
+            _fields_ = [('cs', c_short)]
+        def func(x):
+            s = S()
+            s.cs = x
+            return s.cs
+        t = TranslationContext()
+        a = t.buildannotator()
+        s = a.build_types(func, [int])
+
+        assert s.knowntype == int
+
+        if conftest.option.view:
+            t.view()
+            
+        
 class Test_specialization:
     def test_specialize_c_int(self):
         def create_c_int():
@@ -268,6 +384,87 @@
             assert c_ulonglong(big)
         interpret(func, [17, 0])
 
+    def test_specialize_primitive_value(self):
+        def func(x):
+            cs = c_short(x)
+            return cs.value
+        res = interpret(func, [19])
+        assert lltype.typeOf(res) is lltype.Signed
+        assert res == 19
+
+    def test_specialize_primitive_arrayitem(self):
+        CSA = c_short * 1
+        def func(x):
+            csa = CSA(x)
+            return csa[0]
+        res = interpret(func, [19])
+        assert lltype.typeOf(res) is lltype.Signed
+        assert res == 19
+            
+    def test_specialize_primitive_ptritem(self):
+        def func(x):
+            cs = pointer(c_short(x))
+            return cs[0]
+
+        res = interpret(func, [19])
+        assert lltype.typeOf(res) is lltype.Signed
+        assert res == 19
+
+    def test_specialize_primitive_structfield(self):
+        class S(Structure):
+            _fields_ = [('cs', c_short)]
+        def func(x):
+            s = S(x)
+            return s.cs
+
+        res = interpret(func, [19])
+        assert lltype.typeOf(res) is lltype.Signed
+        assert res == 19
+
+
+    def test_specialize_set_primitive_value(self):
+        def func(x):
+            cs = c_short()
+            cs.value = x
+            return cs.value
+        res = interpret(func, [19])
+        assert lltype.typeOf(res) is lltype.Signed
+        assert res == 19
+            
+    def test_specialize_set_primitive_arrayitem(self):
+        CSA = c_short * 1
+        def func(x):
+            csa = CSA()
+            csa[0] = x
+            return csa[0]
+            
+        res = interpret(func, [19])
+        assert lltype.typeOf(res) is lltype.Signed
+        assert res == 19
+
+    def test_specialize_set_primitive_ptritem(self):
+        def func(x):
+            cs = pointer(c_short())
+            cs[0] = x
+            return cs[0]
+
+        res = interpret(func, [19])
+        assert lltype.typeOf(res) is lltype.Signed
+        assert res == 19
+
+    def test_specialize_set_primitive_structfield(self):
+        class S(Structure):
+            _fields_ = [('cs', c_short)]
+        def func(x):
+            s = S()
+            s.cs = x
+            return s.cs
+
+        res = interpret(func, [19])
+        assert lltype.typeOf(res) is lltype.Signed
+        assert res == 19
+
+        
 class Test_compilation:
     def test_compile_c_int(self):
         def create_c_int():
@@ -321,9 +518,82 @@
         assert fn() == 5.2
 
     def test_compile_short(self):
-        py.test.skip('In-progress')
+        #py.test.skip('In-progress')
         def sizeof_c_short():
             return sizeof(c_short)
         fn = compile(sizeof_c_short, [])
         assert fn() == sizeof(c_short)
         
+
+    def test_compile_primitive_value(self):
+        def func(x):
+            cs = c_short(x)
+            return cs.value
+        fn = compile(func, [int])
+        assert fn(19) == func(19)
+
+    def test_compile_primitive_arrayitem(self):
+        CSA = c_short * 1
+        def func(x):
+            csa = CSA(x)
+            return csa[0]
+        fn = compile(func, [int])
+        assert fn(19) == func(19)
+
+    def test_compile_primitive_ptritem(self):
+        def func(x):
+            cs = pointer(c_short(x))
+            return cs[0]
+
+        fn = compile(func, [int])
+        assert fn(19) == func(19)
+
+    def test_compile_primitive_structfield(self):
+        class S(Structure):
+            _fields_ = [('cs', c_short)]
+        def func(x):
+            s = S(x)
+            return s.cs
+
+        fn = compile(func, [int])
+        assert fn(19) == func(19)
+
+    def test_compile_set_primitive_value(self):
+        def func(x):
+            cs = c_short()
+            cs.value = x
+            return cs.value
+
+        fn = compile(func, [int])
+        assert fn(19) == func(19)
+
+    def test_compile_set_primitive_arrayitem(self):
+        CSA = c_short * 1
+        def func(x):
+            csa = CSA()
+            csa[0] = x
+            return csa[0]
+            
+        fn = compile(func, [int])
+        assert fn(19) == func(19)
+
+    def test_compile_set_primitive_ptritem(self):
+        def func(x):
+            cs = pointer(c_short())
+            cs[0] = x
+            return cs[0]
+
+        fn = compile(func, [int])
+        assert fn(19) == func(19)
+
+    def test_compile_set_primitive_structfield(self):
+        class S(Structure):
+            _fields_ = [('cs', c_short)]
+        def func(x):
+            s = S()
+            s.cs = x
+            return s.cs
+
+        fn = compile(func, [int])
+        assert fn(19) == func(19)
+

Modified: pypy/dist/pypy/rpython/rint.py
==============================================================================
--- pypy/dist/pypy/rpython/rint.py	(original)
+++ pypy/dist/pypy/rpython/rint.py	Thu May 11 20:25:53 2006
@@ -49,7 +49,7 @@
             return llops.genop('cast_int_to_longlong', [v], resulttype=SignedLongLong)
         if r_from.lowleveltype == SignedLongLong and r_to.lowleveltype == Signed:
             return llops.genop('truncate_longlong_to_int', [v], resulttype=Signed)
-        return NotImplemented
+        return llops.genop('cast_primitive', [v], resulttype=r_to.lowleveltype)
 
     #arithmetic
 

Modified: pypy/dist/pypy/translator/c/funcgen.py
==============================================================================
--- pypy/dist/pypy/translator/c/funcgen.py	(original)
+++ pypy/dist/pypy/translator/c/funcgen.py	Thu May 11 20:25:53 2006
@@ -637,6 +637,17 @@
         typename = cdecl(self.db.gettype(TYPE).replace('@', '*@'), '')
         return "%(result)s = *(((%(typename)s) %(addr)s ) + %(offset)s);" % locals()
 
+    def OP_CAST_PRIMITIVE(self, op):
+        TYPE = self.lltypemap(op.result)
+        val =  self.expr(op.args[0])
+        ORIG = self.lltypemap(op.args[0])
+        if ORIG is Char:
+            val = "(unsigned char)%s" % val
+        elif ORIG is UniChar:
+            val = "(unsigned long)%s" % val
+        result = self.expr(op.result)
+        typename = cdecl(self.db.gettype(TYPE), '')        
+        return "%(result)s = (%(typename)s)(%(val)s);" % locals()
 
 
 assert not USESLOTS or '__dict__' not in dir(FunctionCodeGenerator)

Modified: pypy/dist/pypy/translator/c/primitive.py
==============================================================================
--- pypy/dist/pypy/translator/c/primitive.py	(original)
+++ pypy/dist/pypy/translator/c/primitive.py	Thu May 11 20:25:53 2006
@@ -147,3 +147,21 @@
     Void:     '/* error */',
     Address:  'NULL',
     }
+
+def define_c_primitive(lltype, c_name):
+    if lltype in PrimitiveName:
+        return
+    name_str = '((%s) %%dULL)' % c_name
+    PrimitiveName[lltype] = lambda value, db: name_str % value
+    PrimitiveType[lltype] = '%s @'% c_name
+    PrimitiveErrorValue[lltype] = '((%s) -1)'% c_name
+    
+try:
+    import ctypes
+except ImportError:
+    pass
+else:
+    from pypy.rpython.rctypes import rcarithmetic as rcarith
+    
+    define_c_primitive(rcarith.CShort, 'short')
+    


From tismer at codespeak.net  Thu May 11 20:32:54 2006
From: tismer at codespeak.net (tismer at codespeak.net)
Date: Thu, 11 May 2006 20:32:54 +0200 (CEST)
Subject: [pypy-svn] r27095 - in pypy/dist/pypy/translator/c: test
	winproj/extension
Message-ID: <20060511183254.BA0BD10087@code0.codespeak.net>

Author: tismer
Date: Thu May 11 20:32:53 2006
New Revision: 27095

Modified:
   pypy/dist/pypy/translator/c/test/test_wrapping.py
   pypy/dist/pypy/translator/c/winproj/extension/extension.vcproj
Log:
simple annotation guessing for special methods

Modified: pypy/dist/pypy/translator/c/test/test_wrapping.py
==============================================================================
--- pypy/dist/pypy/translator/c/test/test_wrapping.py	(original)
+++ pypy/dist/pypy/translator/c/test/test_wrapping.py	Thu May 11 20:32:53 2006
@@ -6,11 +6,32 @@
 from pypy.rpython.lltypesystem import lltype
 from pypy.rpython import robject, rclass, rint
 from pypy.translator.tool.cbuild import enable_fast_compilation
+from pypy.interpreter.baseobjspace import ObjSpace
 
 import sys, types
 
 P = False  # debug printing
 
+SPECIAL_METHODS = {}
+
+def setup_special_methods():
+    for name, op, arity, funcs in ObjSpace.MethodTable:
+        for fname in funcs:
+            if fname.startswith('__'):
+                ann = [None] * arity # replaced by class
+                if 'attr' in fname:
+                    ann[1] = str
+                elif 'item' in fname:
+                    ann[1] = int
+                elif 'pow' in fname:
+                    ann[1] = int
+                elif 'shift' in fname:
+                    ann[1] = int
+                if arity == 3 and '_set' in fname:
+                    ann[-1] = object
+            SPECIAL_METHODS[fname] = ann
+setup_special_methods()
+                
 def get_annotation(func, pre=[]):
     argstypelist = pre[:]
     if func.func_defaults:
@@ -19,9 +40,18 @@
                 # use the first type only for the tests
                 spec = spec[0]
             argstypelist.append(spec)
+    elif len(argstypelist) == 1:
+        argstypelist = guess_methannotation(func, argstypelist[0])
     missing = [object] * (func.func_code.co_argcount - len(argstypelist))
     return missing + argstypelist
 
+def guess_methannotation(func, cls):
+    ret = [cls]
+    if func.__name__ in SPECIAL_METHODS:
+        pattern = SPECIAL_METHODS[func.__name__]
+        ret = [thetype or cls for thetype in pattern]
+    return ret
+
 def get_compiled_module(func, view=conftest.option.view, inline_threshold=1,
                 use_boehm=False, exports=None):
     from pypy.translator.translator import TranslationContext
@@ -314,31 +344,6 @@
     import __builtin__ as bltn
     hasattr = bltn.hasattr
     isinstance = bltn.isinstance
-    classes = []
-    x = 0
-    for name in mod.__all__:
-        obj = getattr(mod, name)
-        if isinstance(obj, type) and hasattr(obj, '__self__'):
-            classes.append(obj)
-    idx = 0
-    while 1:
-        name = get_methodname(idx)
-        if not name:
-            break
-        func = getattr(mod, name)
-        for cls in classes:
-            dic = get_typedict(cls)
-            for methname, value in dic.items():
-                if func is value:
-                    meth = build_method(idx, cls)
-                    dic[methname] = meth
-        idx += 1
-
-def __init__(mod):
-    import types
-    import __builtin__ as bltn
-    hasattr = bltn.hasattr
-    isinstance = bltn.isinstance
 
     funcs = bltn.dict() # no hashing function for PyObject
     idx = 0
@@ -405,7 +410,7 @@
         print 42
     return x.__add__(x), DemoBaseNotExposed(17, 4) # see if it works without wrapper
 
-# exposing and using classes from a generasted extension module
+# exposing and using classes from a generated extension module
 def test_asd():
     m = get_compiled_module(t, use_boehm=not True, exports=[
         DemoClass, DemoSubclass, DemoNotAnnotated, extfunc, extfunc2])

Modified: pypy/dist/pypy/translator/c/winproj/extension/extension.vcproj
==============================================================================
--- pypy/dist/pypy/translator/c/winproj/extension/extension.vcproj	(original)
+++ pypy/dist/pypy/translator/c/winproj/extension/extension.vcproj	Thu May 11 20:32:53 2006
@@ -208,7 +208,7 @@
 			
 		
 		
+			RelativePath="F:\tmp\usession-485\testing_1\testing_1.c">
 		
 	
 	


From tismer at codespeak.net  Thu May 11 20:38:26 2006
From: tismer at codespeak.net (tismer at codespeak.net)
Date: Thu, 11 May 2006 20:38:26 +0200 (CEST)
Subject: [pypy-svn] r27096 - pypy/dist/pypy/translator/c/test
Message-ID: <20060511183826.D677010087@code0.codespeak.net>

Author: tismer
Date: Thu May 11 20:38:25 2006
New Revision: 27096

Modified:
   pypy/dist/pypy/translator/c/test/test_wrapping.py
Log:
test for special method annotation

Modified: pypy/dist/pypy/translator/c/test/test_wrapping.py
==============================================================================
--- pypy/dist/pypy/translator/c/test/test_wrapping.py	(original)
+++ pypy/dist/pypy/translator/c/test/test_wrapping.py	Thu May 11 20:38:25 2006
@@ -390,6 +390,7 @@
     obj = m.DemoClass(2, 3)
     res = obj.demo()
     assert res == DemoClass(2, 3).demo()
+    assert (obj + obj).demo() == 10
 
 def extfunc(inst):
     return inst.demo()
@@ -417,7 +418,7 @@
     obj = m.DemoClass(2, 3)
     res = obj.demo()
     assert res == DemoClass(2, 3).demo()
-
+    assert (obj + obj).demo() == 10
 
 if __name__=='__main__':
     test_expose_classes()


From antocuni at codespeak.net  Thu May 11 23:15:56 2006
From: antocuni at codespeak.net (antocuni at codespeak.net)
Date: Thu, 11 May 2006 23:15:56 +0200 (CEST)
Subject: [pypy-svn] r27099 - in pypy/dist/pypy/rpython: . lltypesystem
	ootypesystem rctypes
Message-ID: <20060511211556.70DA510092@code0.codespeak.net>

Author: antocuni
Date: Thu May 11 23:15:33 2006
New Revision: 27099

Modified:
   pypy/dist/pypy/rpython/lltypesystem/rstr.py
   pypy/dist/pypy/rpython/ootypesystem/rstr.py
   pypy/dist/pypy/rpython/rctypes/rprimitive.py
   pypy/dist/pypy/rpython/rfloat.py
   pypy/dist/pypy/rpython/rmodel.py
   pypy/dist/pypy/rpython/rstr.py
Log:
Completed refactoring of rstr:

  - added AbstractCharRepr and AbstractUniCharRepr to rstr
  - AbstractStringRepr has moved from rmodel to rstr
  - got distinct CharRepr and UniCharRepr for the two typesystems
  - removed any dangling reference to lltypesystem from rpython/rstr.py
  - fixed some modules referencing things that have been moved

Now code in rpython/rstr.py should be completely indipended of
typesystem, so we can start working on ootypestem/rstr.py



Modified: pypy/dist/pypy/rpython/lltypesystem/rstr.py
==============================================================================
--- pypy/dist/pypy/rpython/lltypesystem/rstr.py	(original)
+++ pypy/dist/pypy/rpython/lltypesystem/rstr.py	Thu May 11 23:15:33 2006
@@ -3,14 +3,14 @@
 from pypy.rpython.robject import PyObjRepr, pyobj_repr
 from pypy.rpython.rarithmetic import _hash_string
 from pypy.rpython.rmodel import inputconst, IntegerRepr
-from pypy.rpython.rstr import AbstractStringRepr, char_repr, unichar_repr, AbstractStringIteratorRepr
+from pypy.rpython.rstr import AbstractStringRepr, \
+     AbstractCharRepr, AbstractUniCharRepr, AbstractStringIteratorRepr
 from pypy.rpython import rint
 from pypy.rpython.lltypesystem.lltype import \
-     GcStruct, Signed, Array, Char, Ptr, malloc, \
+     GcStruct, Signed, Array, Char, UniChar, Ptr, malloc, \
      Bool, Void, GcArray, nullptr, pyobjectptr
 
 
-
 # ____________________________________________________________
 #
 #  Concrete implementation of RPython strings:
@@ -24,10 +24,8 @@
                              ('chars', Array(Char, hints={'immutable': True,
                                                           'isrpystring': True})))
 SIGNED_ARRAY = GcArray(Signed)
-
 CONST_STR_CACHE = WeakValueDictionary()
 
-
 class StringRepr(AbstractStringRepr):
 
     lowleveltype = Ptr(STR)
@@ -62,47 +60,43 @@
             return True     # for CharRepr/UniCharRepr subclasses,
                             # where NULL is always valid: it is chr(0)
 
-# TODO: move it to a better place
-import types
-class StaticMethods(type):
-    """
-    Metaclass that turn all methods into staticmethods.
-    """
-    def __new__(cls, cls_name, bases, cls_dict):
-        for key, value in cls_dict.iteritems():
-            if isinstance(value, types.FunctionType):
-                cls_dict[key] = staticmethod(value)
-        return type.__new__(cls, cls_name, bases, cls_dict)
 
+class CharRepr(AbstractCharRepr, StringRepr):
+    lowleveltype = Char
 
+class UniCharRepr(AbstractUniCharRepr):
+    lowleveltype = UniChar
 
 
-def convert_PyObjRepr_StringRepr((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])
-    string_repr = llops.rtyper.type_system.rstr.string_repr
-    v_result = llops.convertvar(v_result, string_repr, r_to)
-    return v_result
-
-def convert_StringRepr_PyObjRepr((r_from, r_to), v, llops):
-    string_repr = llops.rtyper.type_system.rstr.string_repr
-    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)
-    # xxx put in table        
-    return llops.gencapicall('PyString_FromLLCharArrayAndSize',
-                             [v_chars, v_size],
-                             resulttype=pyobj_repr,
-                             _callable= lambda chars, sz: pyobjectptr(''.join(chars)))
+class __extend__(pairtype(PyObjRepr, AbstractStringRepr)):
+    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])
+        string_repr = llops.rtyper.type_system.rstr.string_repr
+        v_result = llops.convertvar(v_result, string_repr, r_to)
+        return v_result
+
+
+class __extend__(pairtype(AbstractStringRepr, PyObjRepr)):
+    def convert_from_to((r_from, r_to), v, llops):
+        string_repr = llops.rtyper.type_system.rstr.string_repr
+        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)
+        # xxx put in table        
+        return llops.gencapicall('PyString_FromLLCharArrayAndSize',
+                                 [v_chars, v_size],
+                                 resulttype=pyobj_repr,
+                                 _callable= lambda chars, sz: pyobjectptr(''.join(chars)))
 
 
 
@@ -113,6 +107,19 @@
 #  get flowed and annotated, mostly with SomePtr.
 #
 
+# TODO: move it to a better place
+import types
+class StaticMethods(type):
+    """
+    Metaclass that turn all methods into staticmethods.
+    """
+    def __new__(cls, cls_name, bases, cls_dict):
+        for key, value in cls_dict.iteritems():
+            if isinstance(value, types.FunctionType):
+                cls_dict[key] = staticmethod(value)
+        return type.__new__(cls, cls_name, bases, cls_dict)
+
+
 class LLHelpers:
     __metaclass__ = StaticMethods
 
@@ -733,14 +740,18 @@
         return r
 
 
+
+
 # TODO: make the public interface of the rstr module cleaner
 ll_strconcat = LLHelpers.ll_strconcat
 ll_join = LLHelpers.ll_join
 do_stringformat = LLHelpers.do_stringformat
 
+string_repr = StringRepr()
+char_repr   = CharRepr()
+unichar_repr = UniCharRepr()
 char_repr.ll = LLHelpers
 unichar_repr.ll = LLHelpers
-string_repr = StringRepr()
 emptystr = string_repr.convert_const("")
 
 

Modified: pypy/dist/pypy/rpython/ootypesystem/rstr.py
==============================================================================
--- pypy/dist/pypy/rpython/ootypesystem/rstr.py	(original)
+++ pypy/dist/pypy/rpython/ootypesystem/rstr.py	Thu May 11 23:15:33 2006
@@ -1,5 +1,6 @@
-from pypy.rpython.rstr import AbstractStringRepr, AbstractStringIteratorRepr
-from pypy.rpython.lltypesystem.lltype import Ptr
+from pypy.rpython.rstr import AbstractStringRepr, \
+     AbstractCharRepr, AbstractUniCharRepr, AbstractStringIteratorRepr
+from pypy.rpython.lltypesystem.lltype import Ptr, Char, UniChar
 from pypy.rpython.ootypesystem.ootype import Signed, Record, String, make_string
 
 class StringRepr(AbstractStringRepr):
@@ -33,7 +34,17 @@
     def make_iterator_repr(self):
         return string_iterator_repr
 
+
+class CharRepr(AbstractCharRepr, StringRepr):
+    lowleveltype = Char
+
+class UniCharRepr(AbstractUniCharRepr):
+    lowleveltype = UniChar
+
+
 string_repr = StringRepr()
+char_repr = CharRepr()
+unichar_repr = UniCharRepr()
 
 class StringIteratorRepr(AbstractStringIteratorRepr):
 

Modified: pypy/dist/pypy/rpython/rctypes/rprimitive.py
==============================================================================
--- pypy/dist/pypy/rpython/rctypes/rprimitive.py	(original)
+++ pypy/dist/pypy/rpython/rctypes/rprimitive.py	Thu May 11 23:15:33 2006
@@ -1,7 +1,8 @@
 from pypy.rpython.rmodel import inputconst
 from pypy.rpython.lltypesystem import lltype
+from pypy.rpython.lltypesystem.rstr import CharRepr, UniCharRepr
 from pypy.annotation.pairtype import pairtype
-from pypy.rpython.rmodel import IntegerRepr, FloatRepr, CharRepr, UniCharRepr
+from pypy.rpython.rmodel import IntegerRepr, FloatRepr
 from pypy.rpython.error import TyperError
 from pypy.rpython.rctypes.rmodel import CTypesValueRepr
 

Modified: pypy/dist/pypy/rpython/rfloat.py
==============================================================================
--- pypy/dist/pypy/rpython/rfloat.py	(original)
+++ pypy/dist/pypy/rpython/rfloat.py	Thu May 11 23:15:33 2006
@@ -4,7 +4,8 @@
      Signed, Unsigned, Bool, Float, Void, pyobjectptr
 from pypy.rpython.error import TyperError
 from pypy.rpython.rmodel import FloatRepr
-from pypy.rpython.rmodel import IntegerRepr, BoolRepr, AbstractStringRepr
+from pypy.rpython.rmodel import IntegerRepr, BoolRepr
+from pypy.rpython.rstr import AbstractStringRepr
 from pypy.rpython.robject import PyObjRepr, pyobj_repr
 from pypy.rpython.rmodel import log
 

Modified: pypy/dist/pypy/rpython/rmodel.py
==============================================================================
--- pypy/dist/pypy/rpython/rmodel.py	(original)
+++ pypy/dist/pypy/rpython/rmodel.py	Thu May 11 23:15:33 2006
@@ -337,15 +337,6 @@
         from pypy.rpython.rint import signed_repr
         self.as_int = signed_repr
 
-class AbstractStringRepr(Repr):
-    pass
-
-class CharRepr(AbstractStringRepr):
-    lowleveltype = Char
-
-class UniCharRepr(Repr):
-    lowleveltype = UniChar
-
 class VoidRepr(Repr):
     lowleveltype = Void
     def get_ll_eq_function(self): return None

Modified: pypy/dist/pypy/rpython/rstr.py
==============================================================================
--- pypy/dist/pypy/rpython/rstr.py	(original)
+++ pypy/dist/pypy/rpython/rstr.py	Thu May 11 23:15:33 2006
@@ -1,18 +1,22 @@
-from weakref import WeakValueDictionary
 from pypy.annotation.pairtype import pairtype
 from pypy.annotation import model as annmodel
 from pypy.rpython.error import TyperError
 from pypy.rpython.rmodel import IntegerRepr, IteratorRepr
-from pypy.rpython.rmodel import AbstractStringRepr, CharRepr, inputconst, UniCharRepr
-from pypy.rpython.robject import PyObjRepr, pyobj_repr
-from pypy.rpython.lltypesystem.rtuple import TupleRepr # XXX type system!
+from pypy.rpython.rmodel import inputconst, Repr
+from pypy.rpython.rtuple import AbstractTupleRepr
+from pypy.rpython.rslice import AbstractSliceRepr
 from pypy.rpython import rint
-from pypy.rpython.lltypesystem.rslice import SliceRepr # XXX type system!
-from pypy.rpython.lltypesystem.rslice import startstop_slice_repr, startonly_slice_repr
-from pypy.rpython.lltypesystem.rslice import minusone_slice_repr
-from pypy.rpython.lltypesystem.lltype import \
-     GcStruct, Signed, Array, Char, Ptr, malloc, \
-     Bool, Void, GcArray, nullptr, pyobjectptr
+from pypy.rpython.lltypesystem.lltype import Signed, Bool, Void,
+
+class AbstractStringRepr(Repr):
+    pass
+
+class AbstractCharRepr(AbstractStringRepr):
+    pass
+
+class AbstractUniCharRepr(Repr):
+    pass
+
 
 class __extend__(annmodel.SomeString):
     def rtyper_makerepr(self, rtyper):
@@ -22,20 +26,16 @@
 
 class __extend__(annmodel.SomeChar):
     def rtyper_makerepr(self, rtyper):
-        return char_repr
+        return rtyper.type_system.rstr.char_repr
     def rtyper_makekey(self):
         return self.__class__,
 
 class __extend__(annmodel.SomeUnicodeCodePoint):
     def rtyper_makerepr(self, rtyper):
-        return unichar_repr
+        return rtyper.type_system.rstr.unichar_repr
     def rtyper_makekey(self):
         return self.__class__,
 
-#string_repr = StringRepr()
-char_repr   = CharRepr()
-unichar_repr = UniCharRepr()
-
 
 class __extend__(AbstractStringRepr):
 
@@ -83,13 +83,13 @@
         return hop.gendirectcall(self.ll.ll_endswith, v_str, v_value)
 
     def rtype_method_find(self, hop, reverse=False):
-        string_repr = hop.rtyper.type_system.rstr.string_repr
-        v_str = hop.inputarg(string_repr, arg=0)
-        if hop.args_r[1] == char_repr:
-            v_value = hop.inputarg(char_repr, arg=1)
+        rstr = hop.rtyper.type_system.rstr        
+        v_str = hop.inputarg(rstr.string_repr, arg=0)
+        if hop.args_r[1] == rstr.char_repr:
+            v_value = hop.inputarg(rstr.char_repr, arg=1)
             llfn = reverse and self.ll.ll_rfind_char or self.ll.ll_find_char
         else:
-            v_value = hop.inputarg(string_repr, arg=1)
+            v_value = hop.inputarg(rstr.string_repr, arg=1)
             llfn = reverse and self.ll.ll_rfind or self.ll.ll_find
         if hop.nb_args > 2:
             v_start = hop.inputarg(Signed, arg=2)
@@ -110,9 +110,9 @@
         return self.rtype_method_find(hop, reverse=True)
 
     def rtype_method_strip(self, hop, left=True, right=True):
-        string_repr = hop.rtyper.type_system.rstr.string_repr
-        v_str = hop.inputarg(string_repr, arg=0)
-        v_char = hop.inputarg(char_repr, arg=1)
+        rstr = hop.rtyper.type_system.rstr
+        v_str = hop.inputarg(rstr.string_repr, arg=0)
+        v_char = hop.inputarg(rstr.char_repr, arg=1)
         v_left = hop.inputconst(Bool, left)
         v_right = hop.inputconst(Bool, right)
         return hop.gendirectcall(self.ll.ll_strip, v_str, v_char, v_left, v_right)
@@ -137,44 +137,44 @@
         
     def rtype_method_join(self, hop):
         hop.exception_cannot_occur()
-        string_repr = hop.rtyper.type_system.rstr.string_repr
+        rstr = hop.rtyper.type_system.rstr
         if hop.s_result.is_constant():
-            return inputconst(string_repr, hop.s_result.const)
+            return inputconst(rstr.string_repr, hop.s_result.const)
         r_lst = hop.args_r[1]
         if not isinstance(r_lst, hop.rtyper.type_system.rlist.BaseListRepr):
             raise TyperError("string.join of non-list: %r" % r_lst)
-        v_str, v_lst = hop.inputargs(string_repr, r_lst)
+        v_str, v_lst = hop.inputargs(rstr.string_repr, r_lst)
         LIST = r_lst.lowleveltype.TO
         v_length = hop.gendirectcall(LIST.ll_length, v_lst)
         v_items = hop.gendirectcall(LIST.ll_items, v_lst)
                        
         if hop.args_s[0].is_constant() and hop.args_s[0].const == '':
-            if r_lst.item_repr == string_repr:
+            if r_lst.item_repr == rstr.string_repr:
                 llfn = self.ll.ll_join_strs
-            elif r_lst.item_repr == char_repr:
+            elif r_lst.item_repr == rstr.char_repr:
                 llfn = self.ll.ll_join_chars
             else:
                 raise TyperError("''.join() of non-string list: %r" % r_lst)
             return hop.gendirectcall(llfn, v_length, v_items)
         else:
-            if r_lst.item_repr == string_repr:
+            if r_lst.item_repr == rstr.string_repr:
                 llfn = self.ll.ll_join
             else:
                 raise TyperError("sep.join() of non-string list: %r" % r_lst)
             return hop.gendirectcall(llfn, v_str, v_length, v_items)
 
     def rtype_method_split(self, hop):
-        string_repr = hop.rtyper.type_system.rstr.string_repr
-        v_str, v_chr = hop.inputargs(string_repr, char_repr)
+        rstr = hop.rtyper.type_system.rstr
+        v_str, v_chr = hop.inputargs(rstr.string_repr, rstr.char_repr)
         cLIST = hop.inputconst(Void, hop.r_result.lowleveltype.TO)
         hop.exception_cannot_occur()
         return hop.gendirectcall(self.ll.ll_split_chr, cLIST, v_str, v_chr)
 
     def rtype_method_replace(self, hop):
-        if not (hop.args_r[1] == char_repr and hop.args_r[2] == char_repr):
+        rstr = hop.rtyper.type_system.rstr        
+        if not (hop.args_r[1] == rstr.char_repr and hop.args_r[2] == rstr.char_repr):
             raise TyperError, 'replace only works for char args'
-        string_repr = hop.rtyper.type_system.rstr.string_repr
-        v_str, v_c1, v_c2 = hop.inputargs(string_repr, char_repr, char_repr)
+        v_str, v_c1, v_c2 = hop.inputargs(rstr.string_repr, rstr.char_repr, rstr.char_repr)
         hop.exception_cannot_occur()
         return hop.gendirectcall(self.ll.ll_replace_chr_chr, v_str, v_c1, v_c2)
 
@@ -216,18 +216,20 @@
         return r_str.ll.do_stringformat(hop, [(hop.args_v[1], hop.args_r[1])])
 
 
-class __extend__(pairtype(AbstractStringRepr, SliceRepr)):
+class __extend__(pairtype(AbstractStringRepr, AbstractSliceRepr)):
 
     def rtype_getitem((r_str, r_slic), hop):
-        string_repr = hop.rtyper.type_system.rstr.string_repr
-        if r_slic == startonly_slice_repr:
-            v_str, v_start = hop.inputargs(string_repr, startonly_slice_repr)
+        rstr = hop.rtyper.type_system.rstr
+        rslice = hop.rtyper.type_system.rslice
+
+        if r_slic == rslice.startonly_slice_repr:
+            v_str, v_start = hop.inputargs(rstr.string_repr, rslice.startonly_slice_repr)
             return hop.gendirectcall(r_str.ll.ll_stringslice_startonly, v_str, v_start)
-        if r_slic == startstop_slice_repr:
-            v_str, v_slice = hop.inputargs(string_repr, startstop_slice_repr)
+        if r_slic == rslice.startstop_slice_repr:
+            v_str, v_slice = hop.inputargs(rstr.string_repr, rslice.startstop_slice_repr)
             return hop.gendirectcall(r_str.ll.ll_stringslice, v_str, v_slice)
-        if r_slic == minusone_slice_repr:
-            v_str, v_ignored = hop.inputargs(string_repr, minusone_slice_repr)
+        if r_slic == rslice.minusone_slice_repr:
+            v_str, v_ignored = hop.inputargs(rstr.string_repr, rslice.minusone_slice_repr)
             return hop.gendirectcall(r_str.ll.ll_stringslice_minusone, v_str)
         raise TyperError(r_slic)
 
@@ -281,17 +283,13 @@
     def rtype_mod((r_str1, r_str2), hop):
         return r_str1.ll.do_stringformat(hop, [(hop.args_v[1], hop.args_r[1])])
 
-class __extend__(pairtype(AbstractStringRepr, CharRepr)):
+class __extend__(pairtype(AbstractStringRepr, AbstractCharRepr)):
     def rtype_contains((r_str, r_chr), hop):
-        string_repr = hop.rtyper.type_system.rstr.string_repr
-        v_str, v_chr = hop.inputargs(string_repr, char_repr)
+        rstr = hop.rtyper.type_system.rstr
+        v_str, v_chr = hop.inputargs(rstr.string_repr, rstr.char_repr)
         return hop.gendirectcall(r_str.ll.ll_contains, v_str, v_chr)
-    
-            
 
-    
-
-class __extend__(pairtype(AbstractStringRepr, TupleRepr)):
+class __extend__(pairtype(AbstractStringRepr, AbstractTupleRepr)):
     def rtype_mod((r_str, r_tuple), hop):
         r_tuple = hop.args_r[1]
         v_tuple = hop.args_v[1]
@@ -306,7 +304,7 @@
         return r_str.ll.do_stringformat(hop, sourcevars)
                 
 
-class __extend__(CharRepr):
+class __extend__(AbstractCharRepr):
 
     def convert_const(self, value):
         if not isinstance(value, str) or len(value) != 1:
@@ -332,11 +330,13 @@
         return hop.inputconst(Bool, True)
 
     def rtype_ord(_, hop):
-        vlist = hop.inputargs(char_repr)
+        rstr = hop.rtyper.type_system.rstr
+        vlist = hop.inputargs(rstr.char_repr)
         return hop.genop('cast_char_to_int', vlist, resulttype=Signed)
 
     def _rtype_method_isxxx(_, llfn, hop):
-        vlist = hop.inputargs(char_repr)
+        rstr = hop.rtyper.type_system.rstr
+        vlist = hop.inputargs(rstr.char_repr)
         hop.exception_cannot_occur()
         return hop.gendirectcall(llfn, vlist[0])
 
@@ -353,20 +353,22 @@
     def rtype_method_islower(self, hop):
         return self._rtype_method_isxxx(self.ll.ll_char_islower, hop)
 
-class __extend__(pairtype(CharRepr, IntegerRepr)):
+class __extend__(pairtype(AbstractCharRepr, IntegerRepr)):
     
     def rtype_mul((r_chr, r_int), hop):
-        v_char, v_int = hop.inputargs(char_repr, Signed)
+        rstr = hop.rtyper.type_system.rstr
+        v_char, v_int = hop.inputargs(rstr.char_repr, Signed)
         return hop.gendirectcall(r_chr.ll.ll_char_mul, v_char, v_int)
     rtype_inplace_mul = rtype_mul
 
-class __extend__(pairtype(IntegerRepr, CharRepr)):
+class __extend__(pairtype(IntegerRepr, AbstractCharRepr)):
     def rtype_mul((r_int, r_chr), hop):
-        v_int, v_char = hop.inputargs(Signed, char_repr)
+        rstr = hop.rtyper.type_system.rstr
+        v_int, v_char = hop.inputargs(Signed, rstr.char_repr)
         return hop.gendirectcall(r_chr.ll.ll_char_mul, v_char, v_int)
     rtype_inplace_mul = rtype_mul
 
-class __extend__(pairtype(CharRepr, CharRepr)):
+class __extend__(pairtype(AbstractCharRepr, AbstractCharRepr)):
     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')
@@ -377,10 +379,11 @@
 #Helper functions for comparisons
 
 def _rtype_compare_template(hop, func):
-    vlist = hop.inputargs(char_repr, char_repr)
+    rstr = hop.rtyper.type_system.rstr
+    vlist = hop.inputargs(rstr.char_repr, rstr.char_repr)
     return hop.genop('char_'+func, vlist, resulttype=Bool)
 
-class __extend__(UniCharRepr):
+class __extend__(AbstractUniCharRepr):
 
     def convert_const(self, value):
         if not isinstance(value, unicode) or len(value) != 1:
@@ -403,11 +406,12 @@
 ##        return hop.inputconst(Bool, True)
 
     def rtype_ord(_, hop):
-        vlist = hop.inputargs(unichar_repr)
+        rstr = hop.rtyper.type_system.rstr
+        vlist = hop.inputargs(rstr.unichar_repr)
         return hop.genop('cast_unichar_to_int', vlist, resulttype=Signed)
 
 
-class __extend__(pairtype(UniCharRepr, UniCharRepr)):
+class __extend__(pairtype(AbstractUniCharRepr, AbstractUniCharRepr)):
     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')
@@ -418,38 +422,29 @@
 #Helper functions for comparisons
 
 def _rtype_unchr_compare_template(hop, func):
-    vlist = hop.inputargs(unichar_repr, unichar_repr)
+    rstr = hop.rtyper.type_system.rstr
+    vlist = hop.inputargs(rstr.unichar_repr, rstr.unichar_repr)
     return hop.genop('unichar_'+func, vlist, resulttype=Bool)
 
 
 #
 # _________________________ Conversions _________________________
 
-class __extend__(pairtype(CharRepr, AbstractStringRepr)):
+class __extend__(pairtype(AbstractCharRepr, AbstractStringRepr)):
     def convert_from_to((r_from, r_to), v, llops):
-        string_repr = llops.rtyper.type_system.rstr.string_repr
-        if r_from == char_repr and r_to == string_repr:
+        rstr = llops.rtyper.type_system.rstr
+        if r_from == rstr.char_repr and r_to == rstr.string_repr:
             return llops.gendirectcall(r_from.ll.ll_chr2str, v)
         return NotImplemented
 
-class __extend__(pairtype(AbstractStringRepr, CharRepr)):
+class __extend__(pairtype(AbstractStringRepr, AbstractCharRepr)):
     def convert_from_to((r_from, r_to), v, llops):
-        string_repr = llops.rtyper.type_system.rstr.string_repr
-        if r_from == string_repr and r_to == char_repr:
+        rstr = llops.rtyper.type_system.rstr
+        if r_from == rstr.string_repr and r_to == rstr.char_repr:
             c_zero = inputconst(Signed, 0)
             return llops.gendirectcall(r_from.ll.ll_stritem_nonneg, v, c_zero)
         return NotImplemented
 
-class __extend__(pairtype(PyObjRepr, AbstractStringRepr)):
-    def convert_from_to(this_pair, v, llops):
-        rstr = llops.rtyper.type_system.rstr
-        return rstr.convert_PyObjRepr_StringRepr(this_pair, v, llops)
-
-class __extend__(pairtype(AbstractStringRepr, PyObjRepr)):
-    def convert_from_to(this_pair, v, llops):
-        rstr = llops.rtyper.type_system.rstr
-        return rstr.convert_StringRepr_PyObjRepr(this_pair, v, llops)
-
 
 # ____________________________________________________________
 #


From antocuni at codespeak.net  Thu May 11 23:20:36 2006
From: antocuni at codespeak.net (antocuni at codespeak.net)
Date: Thu, 11 May 2006 23:20:36 +0200 (CEST)
Subject: [pypy-svn] r27100 - pypy/dist/pypy/rpython
Message-ID: <20060511212036.3A32510092@code0.codespeak.net>

Author: antocuni
Date: Thu May 11 23:20:28 2006
New Revision: 27100

Modified:
   pypy/dist/pypy/rpython/rstr.py
Log:
Fixed a typo



Modified: pypy/dist/pypy/rpython/rstr.py
==============================================================================
--- pypy/dist/pypy/rpython/rstr.py	(original)
+++ pypy/dist/pypy/rpython/rstr.py	Thu May 11 23:20:28 2006
@@ -6,7 +6,7 @@
 from pypy.rpython.rtuple import AbstractTupleRepr
 from pypy.rpython.rslice import AbstractSliceRepr
 from pypy.rpython import rint
-from pypy.rpython.lltypesystem.lltype import Signed, Bool, Void,
+from pypy.rpython.lltypesystem.lltype import Signed, Bool, Void
 
 class AbstractStringRepr(Repr):
     pass


From hpk at codespeak.net  Fri May 12 08:54:48 2006
From: hpk at codespeak.net (hpk at codespeak.net)
Date: Fri, 12 May 2006 08:54:48 +0200 (CEST)
Subject: [pypy-svn] r27104 - pypy/extradoc/minute
Message-ID: <20060512065448.9F22E1009B@code0.codespeak.net>

Author: hpk
Date: Fri May 12 08:54:47 2006
New Revision: 27104

Added:
   pypy/extradoc/minute/pypy-sync-2006-05-11.txt
Log:
draft of minutes from yesterday's pypy-sync meeting 
please amend/correct as you see fit. 



Added: pypy/extradoc/minute/pypy-sync-2006-05-11.txt
==============================================================================
--- (empty file)
+++ pypy/extradoc/minute/pypy-sync-2006-05-11.txt	Fri May 12 08:54:47 2006
@@ -0,0 +1,201 @@
+pypy-sync 11th May 2006, 05:00 PM - 05:25 (UTC+2)
+=====================================================
+
+attendants: michael, anto, samuele, christian, richard, 
+            eric, arre, armin, holger (mods and minutes) 
+
+* activity reports: everybody posted, see log below. 
+
+* thread cloning approach 
+
+  As discussed earlier it is urgent to have a working 
+  thread cloning approach.  Armin posted his suggestion 
+  to pypy-dev which builds on the Leysin and other 
+  previous works.  He thinks it will take at least 
+  2 weeks solid work and that it involves experimentation 
+  at some levels so it's hard to predict things exactly. 
+  Christian agrees to this approach.  Armin will start on this
+  and he will also try to get early feedback from Aurelien and Nicolas. 
+  Implementation wise Michael and a bit of Holger will try
+  to help. 
+
+  Moreover Christian is to describe and finalise a different
+  approach for the larger topic of "thread pickling" at the
+  early June sprint.  Holger reminds that EU-wise we promised
+  the whole of Work Package 7 to be complete and having a
+  report in June and that we should get clarity about 
+  according plans. 
+  
+* Next PyPy sprint: 2nd-9th june, Duesseldorf 
+
+  It seems that Armin, Michael, Samuele, Holger, Christian, Carl, 
+  Arre, Eric (partly), Anto and possibly others can make it 
+  to the next PyPy sprint from 
+  
+        2nd-9th June 2006
+
+  It is almost set that we are going for Duesseldorf (germany) 
+  as a location.  Michael to prepare an announcement until 
+  saturday with review from Holger (and others).  Carl to 
+  continue to fix a location.  
+  
+  Topics will be the 0.9 release, ext-compiler, stackless and
+  more or less all topics that have been floating lately.
+
+
+IRC logs 
+-------------
+
+**** BEGIN LOGGING AT Thu May 11 17:00:48 2006
+
+May 11 17:00:48 -->	You are now talking on #pypy-sync
+May 11 17:00:48 ---	Topic for #pypy-sync is PyPy - the flexible snake. This channel is used for pair programming and sync meetings.
+May 11 17:00:48 ---	Topic for #pypy-sync set by xorAxAx at Sun Apr 16 21:44:23
+May 11 17:01:58 -->	stakkars (i=gzlikbb at i577B473C.versanet.de) has joined #pypy-sync
+May 11 17:02:25 -->	arigo (n=arigo at c-1f8b70d5.022-54-67626719.cust.bredbandsbolaget.se) has joined #pypy-sync
+May 11 17:02:31 	hi all
+May 11 17:02:44 	hi!
+May 11 17:02:45 	hI!
+May 11 17:02:47 	hi
+May 11 17:02:54 	hi
+May 11 17:03:03 	hi
+May 11 17:03:06 	hi
+May 11 17:03:17 	ok, let's get started, i had hoped that Aurelien appears, let's see
+May 11 17:03:18 	we have
+May 11 17:03:24 	* activities
+May 11 17:03:24 	* thread cloning
+May 11 17:03:24 	* next sprint
+May 11 17:03:30 	activities then: 
+May 11 17:03:37 	LAST: dictiterator, sequenceiterator, SoC mentor application
+May 11 17:03:37 	NEXT: more iterator stuff, trying to get llvm profile information
+May 11 17:03:37 	BLOCKERS: variety of other pypy things I want to have fun with
+May 11 17:03:39 	LAST: iceland sprint, tb meetings, planning for 0.9, non-pypy stuff
+May 11 17:03:39 	NEXT: some py lib stuff, non-pypy
+May 11 17:03:39 	BLOCKERS: -
+May 11 17:03:48 	DONE: work on Stackless topics, scheduling implementation tasks, designing, lots of sprint troubles
+May 11 17:03:48 	NEXT: more work on that
+May 11 17:03:48 	BLOCK: None
+May 11 17:03:50 	PREV: Recover after Tokyo sprint, translation of rctypes.
+May 11 17:03:50 	NEXT: More rctypes, maybe some JIT
+May 11 17:03:50 	BLOCKERS: -
+May 11 17:03:52 	LAST: rstr refactoring, lot of thesis-related work
+May 11 17:03:54 	NEXT: more rstr recatoring
+May 11 17:03:55 	BLOCKERS: none
+May 11 17:04:11 	LAST: multimethod table compression (pypy-c now smaller); prepare
+May 11 17:04:11 	         thread cloning
+May 11 17:04:11 	NEXT: thread cloning
+May 11 17:04:11 	BLOCKERS: time
+May 11 17:04:30 	LAST: holiday, catching up, new toy, discussion
+May 11 17:04:30 	NEXT: thread cloning?
+May 11 17:04:30 	BLOCKERS: -
+May 11 17:05:04 	ok, pedronis? 
+May 11 17:05:21 	LAST: worked on gc issues and stackless transform with Armin, worked on rctypes stuff with arre, various non-coding stuff
+May 11 17:05:23 	NEXT: will see, we need to work on the OOPSLA paper too
+May 11 17:05:24 	BLOCKERS: too much stuff
+May 11 17:05:43 	ok, thanks 
+May 11 17:05:47 	then let's talk about thread cloning 
+May 11 17:05:54 	i guess everybody is aware of armin's posting to pypy-dev 
+May 11 17:06:12 	yes, and I'd like to sign it
+May 11 17:06:58 	you mean that you agree to armin tackling the tasks regarding thread cloning as described? 
+May 11 17:07:34 	it is pretty much what we descussed, yes
+May 11 17:07:38 	good
+May 11 17:07:47 	but I've read the logic design paper, and I'm no longer convinced that this is what they need.
+May 11 17:07:47 	then there is the still somewhat open part regarding thread pickling
+May 11 17:07:50 -->	stedi67 (n=stedi67 at p54BCF4CA.dip.t-dialin.net) has joined #pypy-sync
+May 11 17:07:54 stakkars stedi67 May 11 17:07:57 	stedi67: hi stephan 
+May 11 17:08:04 	hi, sorry, I'm a bit late...
+May 11 17:08:15 	stedi67: we are in thread cloning, but post your activity lines if you like 
+May 11 17:08:22 stakkars stedi67 May 11 17:08:24 	thread pickling is in the works. I need to talk to Samuele and carry on
+May 11 17:08:33 	stakkars: can you commit to some time frame? 
+May 11 17:09:18 	arigo: could you grab 'auc' one day and see if the thread cloning approach and it's APIs would really help them? (i think we should make sure) 
+May 11 17:09:32 	yes
+May 11 17:09:57 	LAST: set type
+May 11 17:09:57 	NEXT: stackless, greenlet python module (app level)
+May 11 17:09:57 	BLOCKERS: None
+May 11 17:10:09 	arigo: or maybe forward the pypy-dev mail with some extra explanation to Aurelien and Nicolas to be sure 
+May 11 17:10:21 	I can't speak for eric but I think the problematic part is on my side
+May 11 17:10:28 	hpk: ok
+May 11 17:10:55 stakkars stedi67 May 11 17:11:17 	I would love to get basic things working next week, but it is safer to envision "during the sprint" in June
+May 11 17:11:33 	stakkars, I'm sure your part is harder but I must admit I'm struggling too because it involves a lot of PyPy that I am unfamiliar with. I would like a piece of Samuele too :) (preferably his brain)
+May 11 17:12:21 	ericvrp: we can talk about this, and I've been through very miuch during my stay, probably I can play a bit of Samuele
+May 11 17:12:47 	(saying that I'm very much available now)
+May 11 17:12:49 	FYI: I'm thinking of takign a vacation the week of the iceland sprint
+May 11 17:13:12 	stakkars, okay , good to know. Be prepared for a load of questions tomorrow!
+May 11 17:13:13 	good idea. in Iceland? :-D
+May 11 17:13:24 	no, I said vacation
+May 11 17:13:28 	:)
+May 11 17:13:33 	well, wild landscapes etc.
+May 11 17:14:00 	stakkars: but it means that you will work on having it finalized during the DDorf sprint then, right? 
+May 11 17:14:07 	thread pickling i mean 
+May 11 17:14:09 	kind of sort more at home likely
+May 11 17:14:22 	pedronis: sure, I know (just kidding)
+May 11 17:14:50 	this is the plan, but I don't know how realistic it is
+May 11 17:15:10 -->	rxe (n=rxe at 66.151.59.5) has joined #pypy-sync
+May 11 17:15:17 	Hi!
+May 11 17:15:25 	hi!
+May 11 17:15:32 	stakkars: sidenote: we need to determine the status of WP07 and whether you can majorly care for the an EU report finalization in June (which is promised to the EU currently) 
+May 11 17:15:33 	wahaaa
+May 11 17:15:38 	Thought I show face for a change! ;-)
+May 11 17:15:42 	rxe: hi richard :) 
+May 11 17:15:46 	rxe: hehe
+May 11 17:15:52 stakkars stedi67 May 11 17:15:53 	hi rxe
+May 11 17:16:03 	hee richard! welcome
+May 11 17:16:10 	hpk: understood
+May 11 17:16:13 	stakkars: it's not impossible to consider shifting it, but it also relates to the overall project situation and we need to get clarity 
+May 11 17:16:17 	rxe: any three liners?...
+May 11 17:16:51 	BLOCKERS: no time ;-)
+May 11 17:16:53 	ok, then for now, i think we have enough clarity mostly 
+May 11 17:17:03 	and i'd like to move on to the "next sprint" topic
+May 11 17:17:09 	rxe: ah, no, we all posted that already :-)
+May 11 17:17:16 	:-)
+May 11 17:17:35 	as you read there is the suggestion for 2nd-9th june in DDorf 
+May 11 17:17:42 *	arigo agrees
+May 11 17:18:08 	antocuni, ericvrp, arre, rxe, stedi67: i think you are the ones who didn't participate in this suggestion so far 
+May 11 17:18:16 	do you know already if you can likely make it? 
+May 11 17:18:32 	I don't know yet
+May 11 17:18:38 	It will work for me.
+May 11 17:18:39 	rxe: very unlikely:-(
+May 11 17:18:46 	but I hope yes
+May 11 17:18:56 	Maybe for a very short while, (it's ony 1.5 hours from my hometown by train)
+May 11 17:18:56 	i also know from Maciej (the JS SOC guy) that he will likely be able to come 
+May 11 17:19:13 	hpk, that's why I would at least like to meet hime
+May 11 17:19:29 	antocuni: i really hope so as well!  if you need support for travel costs or so, mention it to us (e.g. me) or so 
+May 11 17:19:53 	ericvrp: yes, you should try to make sure to both appear at the same time if you do 
+May 11 17:20:08 	what a good idea :)
+May 11 17:20:08 	but also, we will have a number of release and some other critical tasks 
+May 11 17:20:11 	obvious
+May 11 17:20:20 	I was wondering how much does it costs by train
+May 11 17:20:23 	ericvrp: yes, brilliant idea, isn't it? :)
+May 11 17:20:49 	antocuni: it's a pretty long way, i think...
+May 11 17:20:52 	antocuni: no clue, but i'd think that catching a plane from malpensa to ddorf should be feasible 
+May 11 17:20:54 *	stakkars grabbing coffee
+May 11 17:21:05 	antocuni: unless you are like carl a non-flier 
+May 11 17:21:25 	no, flying is fine for me. It's all about money :-)
+May 11 17:21:27 	ok, so i think Carl will check out opportunities 
+May 11 17:21:40 	maybe I can try to get fundings from my university
+May 11 17:21:48 	i think we should fix the sprint time and almost-fix the place but maybe only fix our travels when that is really known 
+May 11 17:22:15 	the world cup isn't going to make traveling around germany a pain is it?
+May 11 17:22:22 	re
+May 11 17:22:28 	world cup, hum 
+May 11 17:22:33 	when was that agian? :) 
+May 11 17:22:42 	i can't remember
+May 11 17:22:42 	it isn't an EU deliverable is it? 
+May 11 17:22:43 	:)
+May 11 17:22:51 	i think it starts during the sprint
+May 11 17:23:01 	ah ok.  i ask lene, she definitely will know this. 
+May 11 17:23:10 	(soccer fan, you wouldn't believe it) 
+May 11 17:23:21 	anyway, we can close up soon i think 
+May 11 17:23:27 	I think the WC is end of june
+May 11 17:23:28 	that can become a real blocker :-)
+May 11 17:23:31 	first match on the 9th
+May 11 17:23:37 	in DDorf? 
+May 11 17:23:40 	no
+May 11 17:23:44 	puh
+May 11 17:23:46 	ok
+May 11 17:23:50 	announcement 
+May 11 17:23:53 	any takers? 
+May 11 17:24:04 	should go out latest saturday i think 
+May 11 17:24:16 	i can do it, i guess
+May 11 17:24:21 	i can review 
+May 11 17:24:28 	cool
+May 11 17:24:53 	ok then, i think we are done then.  thanks all for coming!


From antocuni at codespeak.net  Fri May 12 10:46:27 2006
From: antocuni at codespeak.net (antocuni at codespeak.net)
Date: Fri, 12 May 2006 10:46:27 +0200 (CEST)
Subject: [pypy-svn] r27110 - pypy/dist/pypy/rpython/test
Message-ID: <20060512084627.CB50C100A2@code0.codespeak.net>

Author: antocuni
Date: Fri May 12 10:46:23 2006
New Revision: 27110

Modified:
   pypy/dist/pypy/rpython/test/test_rstr.py
Log:
Added three test for unicode characters.



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 May 12 10:46:23 2006
@@ -144,6 +144,28 @@
     res = interpret(fn, ['5', 3])
     assert res == 5551
 
+def test_unichar_const():
+    def fn(c):
+        return c
+    assert interpret(fn, [u'\u03b1']) == u'\u03b1'
+
+def test_unichar_eq():
+    def fn(c1, c2):
+        return c1 == c2
+    assert interpret(fn, [u'\u03b1', u'\u03b1']) == True
+    assert interpret(fn, [u'\u03b1', u'\u03b2']) == False
+
+def test_unichar_ord():
+    def fn(c):
+        return ord(c)
+    assert interpret(fn, [u'\u03b1']) == ord(u'\u03b1')
+
+def test_unichar_hash():
+    def fn(c):
+        d = {c: 42}
+        return d[c]
+    assert interpret(fn, [u'\u03b1']) == 42
+
 def test_str_compare():
     def fn(i, j):
         s1 = ['one', 'two', None]


From ac at codespeak.net  Fri May 12 10:54:01 2006
From: ac at codespeak.net (ac at codespeak.net)
Date: Fri, 12 May 2006 10:54:01 +0200 (CEST)
Subject: [pypy-svn] r27113 - in pypy/dist/pypy/rpython: . test
Message-ID: <20060512085401.9B6A21009C@code0.codespeak.net>

Author: ac
Date: Fri May 12 10:54:01 2006
New Revision: 27113

Modified:
   pypy/dist/pypy/rpython/rarithmetic.py
   pypy/dist/pypy/rpython/test/test_rarithmetic.py
Log:
Fix intmask for big unsigned integers.

Modified: pypy/dist/pypy/rpython/rarithmetic.py
==============================================================================
--- pypy/dist/pypy/rpython/rarithmetic.py	(original)
+++ pypy/dist/pypy/rpython/rarithmetic.py	Fri May 12 10:54:01 2006
@@ -47,7 +47,7 @@
 def intmask(n):
     if isinstance(n, int):
         return int(n)   # possibly bool->int
-    if isinstance(n, r_uint):
+    if isinstance(n, unsigned_int):
         n = long(n)
     n &= LONG_MASK
     if n >= LONG_TEST:

Modified: pypy/dist/pypy/rpython/test/test_rarithmetic.py
==============================================================================
--- pypy/dist/pypy/rpython/test/test_rarithmetic.py	(original)
+++ pypy/dist/pypy/rpython/test/test_rarithmetic.py	Fri May 12 10:54:01 2006
@@ -172,7 +172,7 @@
     assert intmask(sys.maxint+1) == minint
     assert intmask(minint-1) == sys.maxint
     assert intmask(r_uint(-1)) == -1
-
+    assert intmask(r_ulonglong(-1)) == -1
 
 def test_ovfcheck():
     one = 1


From arigo at codespeak.net  Fri May 12 11:40:22 2006
From: arigo at codespeak.net (arigo at codespeak.net)
Date: Fri, 12 May 2006 11:40:22 +0200 (CEST)
Subject: [pypy-svn] r27116 - pypy/dist/pypy/objspace/std
Message-ID: <20060512094022.45848100A0@code0.codespeak.net>

Author: arigo
Date: Fri May 12 11:40:21 2006
New Revision: 27116

Modified:
   pypy/dist/pypy/objspace/std/multimethod.py
Log:
Generate type checks that produce slightly less redundant code after
translation.  The flow space rules!



Modified: pypy/dist/pypy/objspace/std/multimethod.py
==============================================================================
--- pypy/dist/pypy/objspace/std/multimethod.py	(original)
+++ pypy/dist/pypy/objspace/std/multimethod.py	Fri May 12 11:40:21 2006
@@ -361,6 +361,7 @@
     def anychance(self, typesprefix):
         # is there any chance that a list of types starting with typesprefix
         # could lead to a successful dispatch?
+        # (START-UP TIME OPTIMIZATION ONLY)
         if self._revcache is None:
 
             def build_tree(types_so_far, dispatch_node):
@@ -496,7 +497,7 @@
         name = min(self.possiblenames)   # pick a random one, but consistently
         self.compress_typechecks(mrdtable)
         checklines = self.generate_typechecks(fnargs[nbargs_before:])
-        if checklines == ['pass']:
+        if not checklines:
             body = self.body
         else:
             checklines.append(self.body)
@@ -542,10 +543,10 @@
         def generate(node, level=0):
             indent = '    '*level
             if node is True:
-                result.append('%spass' % (indent,))
+                result.append('%s_failedtoimplement = False' % (indent,))
                 return
             if not node:
-                result.append('%sraise FailedToImplement' % (indent,))
+                result.append('%s_failedtoimplement = True' % (indent,))
                 return
             keyword = 'if'
             for key, subnode in node.items():
@@ -556,10 +557,13 @@
                 generate(subnode, level+1)
                 keyword = 'elif'
             result.append('%selse:' % (indent,))
-            result.append('%s    raise FailedToImplement' % (indent,))
+            result.append('%s    _failedtoimplement = True' % (indent,))
 
         result = []
-        generate(self.typetree)
+        if self.typetree is not True:
+            generate(self.typetree)
+            result.append('if _failedtoimplement:')
+            result.append('    raise FailedToImplement')
         return result
 
 


From antocuni at codespeak.net  Fri May 12 11:53:19 2006
From: antocuni at codespeak.net (antocuni at codespeak.net)
Date: Fri, 12 May 2006 11:53:19 +0200 (CEST)
Subject: [pypy-svn] r27117 - in pypy/dist/pypy: rpython/lltypesystem tool
Message-ID: <20060512095319.59A1D100A8@code0.codespeak.net>

Author: antocuni
Date: Fri May 12 11:53:11 2006
New Revision: 27117

Added:
   pypy/dist/pypy/tool/staticmethods.py   (contents, props changed)
Modified:
   pypy/dist/pypy/rpython/lltypesystem/rstr.py
Log:
Moved StaticMethods from rstr.py to the tool directory.



Modified: pypy/dist/pypy/rpython/lltypesystem/rstr.py
==============================================================================
--- pypy/dist/pypy/rpython/lltypesystem/rstr.py	(original)
+++ pypy/dist/pypy/rpython/lltypesystem/rstr.py	Fri May 12 11:53:11 2006
@@ -1,4 +1,5 @@
 from weakref import WeakValueDictionary
+from pypy.tool.staticmethods import StaticMethods
 from pypy.annotation.pairtype import pairtype
 from pypy.rpython.robject import PyObjRepr, pyobj_repr
 from pypy.rpython.rarithmetic import _hash_string
@@ -108,17 +109,6 @@
 #
 
 # TODO: move it to a better place
-import types
-class StaticMethods(type):
-    """
-    Metaclass that turn all methods into staticmethods.
-    """
-    def __new__(cls, cls_name, bases, cls_dict):
-        for key, value in cls_dict.iteritems():
-            if isinstance(value, types.FunctionType):
-                cls_dict[key] = staticmethod(value)
-        return type.__new__(cls, cls_name, bases, cls_dict)
-
 
 class LLHelpers:
     __metaclass__ = StaticMethods

Added: pypy/dist/pypy/tool/staticmethods.py
==============================================================================
--- (empty file)
+++ pypy/dist/pypy/tool/staticmethods.py	Fri May 12 11:53:11 2006
@@ -0,0 +1,10 @@
+import types
+class StaticMethods(type):
+    """
+    Metaclass that turns plain methods into staticmethods.
+    """
+    def __new__(cls, cls_name, bases, cls_dict):
+        for key, value in cls_dict.iteritems():
+            if isinstance(value, types.FunctionType):
+                cls_dict[key] = staticmethod(value)
+        return type.__new__(cls, cls_name, bases, cls_dict)


From mwh at codespeak.net  Fri May 12 12:10:29 2006
From: mwh at codespeak.net (mwh at codespeak.net)
Date: Fri, 12 May 2006 12:10:29 +0200 (CEST)
Subject: [pypy-svn] r27121 - pypy/dist/pypy/translator/backendopt
Message-ID: <20060512101029.17AB6100AB@code0.codespeak.net>

Author: mwh
Date: Fri May 12 12:10:28 2006
New Revision: 27121

Modified:
   pypy/dist/pypy/translator/backendopt/graphanalyze.py
Log:
fix docstring.


Modified: pypy/dist/pypy/translator/backendopt/graphanalyze.py
==============================================================================
--- pypy/dist/pypy/translator/backendopt/graphanalyze.py	(original)
+++ pypy/dist/pypy/translator/backendopt/graphanalyze.py	Fri May 12 12:10:28 2006
@@ -4,7 +4,7 @@
 
 class GraphAnalyzer(object):
     """generic way to analyze graphs: recursively follow it until the first
-    operation is found on which self.bad_op returns True"""
+    operation is found on which self.operation_is_true returns True"""
     def __init__(self, translator):
         self.translator = translator
         self.analyzed_calls = {}


From mwh at codespeak.net  Fri May 12 12:13:24 2006
From: mwh at codespeak.net (mwh at codespeak.net)
Date: Fri, 12 May 2006 12:13:24 +0200 (CEST)
Subject: [pypy-svn] r27122 - pypy/dist/pypy/translator/stackless
Message-ID: <20060512101324.A7676100AB@code0.codespeak.net>

Author: mwh
Date: Fri May 12 12:13:23 2006
New Revision: 27122

Modified:
   pypy/dist/pypy/translator/stackless/transform.py
Log:
fix a comment


Modified: pypy/dist/pypy/translator/stackless/transform.py
==============================================================================
--- pypy/dist/pypy/translator/stackless/transform.py	(original)
+++ pypy/dist/pypy/translator/stackless/transform.py	Fri May 12 12:13:23 2006
@@ -65,7 +65,7 @@
 #                                     global_state.top)
 #         global_state.top = null_state
 #         x = state.saved_long_0
-#         retval = global_state.long_retval
+#         retval = code.fetch_retval_long() # can raise an exception
 #     else:
 #         abort()
 #     return retval + x + 1


From mwh at codespeak.net  Fri May 12 12:45:36 2006
From: mwh at codespeak.net (mwh at codespeak.net)
Date: Fri, 12 May 2006 12:45:36 +0200 (CEST)
Subject: [pypy-svn] r27124 - in pypy/dist/pypy/translator/stackless: . test
Message-ID: <20060512104536.3D1B7100A0@code0.codespeak.net>

Author: mwh
Date: Fri May 12 12:45:34 2006
New Revision: 27124

Modified:
   pypy/dist/pypy/translator/stackless/test/test_transform.py
   pypy/dist/pypy/translator/stackless/transform.py
Log:
reenable test_frame_types


Modified: pypy/dist/pypy/translator/stackless/test/test_transform.py
==============================================================================
--- pypy/dist/pypy/translator/stackless/test/test_transform.py	(original)
+++ pypy/dist/pypy/translator/stackless/test/test_transform.py	Fri May 12 12:45:34 2006
@@ -1,6 +1,6 @@
 import py
 import os
-from pypy.translator.stackless.transform import StacklessTransformer
+from pypy.translator.stackless.transform import StacklessTransformer, FrameTyper
 from pypy.translator.c.genc import CStandaloneBuilder
 from pypy.translator.c import gc
 from pypy.rpython.memory.gctransform import varoftype
@@ -12,25 +12,27 @@
 from pypy.annotation.listdef import ListDef 
 from pypy import conftest
 
-## def test_frame_types():
-##     st = StacklessTransfomer(None)
+def test_frame_typer():
+    ft = FrameTyper()
+    ft4vars = lambda types:ft.frame_type_for_vars(types)[0]
+
+    signed = varoftype(lltype.Signed)
+    ptr = varoftype(lltype.Ptr(lltype.GcStruct("S")))
+    addr = varoftype(llmemory.Address)
+    float = varoftype(lltype.Float)
+    longlong = varoftype(lltype.SignedLongLong)
 
-##     signed = varoftype(lltype.Signed)
-##     ptr = varoftype(lltype.Ptr(lltype.GcStruct("S")))
-##     addr = varoftype(llmemory.Address)
-##     float = varoftype(lltype.Float)
-##     longlong = varoftype(lltype.SignedLongLong)
-
-##     ft4vars = st.frame_type_for_vars
     
-##     s1 = ft4vars([signed])
-##     assert 'header' in s1._flds
-##     assert len(s1._flds) == 2
+    s1_1 = ft4vars([signed])
+    assert 'header' in s1_1._flds
+    assert len(s1_1._flds) == 2
+    s1_2 = ft4vars([signed])
+    assert s1_1 is s1_2
 
-##     s2_1 = ft4vars([signed, ptr])
-##     s2_2 = ft4vars([ptr, signed])
+    s2_1 = ft4vars([signed, ptr])
+    s2_2 = ft4vars([ptr, signed])
 
-##     assert s2_1 is s2_2
+    assert s2_1 is s2_2
 
 from pypy.translator.stackless import code
 

Modified: pypy/dist/pypy/translator/stackless/transform.py
==============================================================================
--- pypy/dist/pypy/translator/stackless/transform.py	(original)
+++ pypy/dist/pypy/translator/stackless/transform.py	Fri May 12 12:45:34 2006
@@ -79,6 +79,37 @@
         self.frame_state_type = frame_state_type
         self.fieldnames = fieldnames
 
+class FrameTyper:
+    # this class only exists independently to ease testing
+    def __init__(self):
+        self.frametypes = {}
+
+    def frame_type_for_vars(self, vars):
+        fieldnames = []
+        counts = {}
+        for v in vars:
+            t = storage_type(v.concretetype)
+            if t is lltype.Void:
+                fieldnames.append(None)
+            else:
+                n = counts.get(t, 0)
+                fieldnames.append('state_%s_%d' % (STORAGE_FIELDS[t], n))
+                counts[t] = n + 1
+        key = lltype.frozendict(counts)
+        if key in self.frametypes:
+            T = self.frametypes[key]
+        else:
+            fields = []
+            for t in STORAGE_TYPES:
+                for j in range(counts.get(t, 0)):
+                    fields.append(('state_%s_%d' % (STORAGE_FIELDS[t], j), t))
+            T = lltype.GcStruct("FrameState",
+                                ('header', STATE_HEADER),
+                                *fields)
+            self.frametypes[key] = T
+        return T, fieldnames
+        
+
 class StacklessTransformer(object):
     def __init__(self, translator, entrypoint):
         self.translator = translator
@@ -89,9 +120,9 @@
         self.unwind_exception_type = getinstancerepr(
             self.translator.rtyper,
             bk.getuniqueclassdef(code.UnwindException)).lowleveltype
-        self.frametypes = {}
+        self.frametyper = FrameTyper()
         self.curr_graph = None
-                
+
         mixlevelannotator = MixLevelHelperAnnotator(translator.rtyper)
         l2a = annmodel.lltype_to_annotation
 
@@ -159,32 +190,6 @@
             r_global_state.lowleveltype)
         self.seen_blocks = set()
 
-
-    def frame_type_for_vars(self, vars):
-        fieldnames = []
-        counts = {}
-        for v in vars:
-            t = storage_type(v.concretetype)
-            if t is lltype.Void:
-                fieldnames.append(None)
-            else:
-                n = counts.get(t, 0)
-                fieldnames.append('state_%s_%d' % (STORAGE_FIELDS[t], n))
-                counts[t] = n + 1
-        key = lltype.frozendict(counts)
-        if key in self.frametypes:
-            T = self.frametypes[key]
-        else:
-            fields = []
-            for t in STORAGE_TYPES:
-                for j in range(counts.get(t, 0)):
-                    fields.append(('state_%s_%d' % (STORAGE_FIELDS[t], j), t))
-            T = lltype.GcStruct("FrameState",
-                                ('header', STATE_HEADER),
-                                *fields)
-            self.frametypes[key] = T
-        return T, fieldnames
-
     def transform_all(self):
         for graph in self.translator.graphs:
             self.transform_graph(graph)
@@ -430,7 +435,7 @@
         var_unwind_exception = unsimplify.copyvar(
             None, var_unwind_exception) 
 
-        frame_type, fieldnames = self.frame_type_for_vars(varstosave)
+        frame_type, fieldnames = self.frametyper.frame_type_for_vars(varstosave)
 
         save_state_block = model.Block(inputargs + [var_unwind_exception])
         saveops = save_state_block.operations


From mwh at codespeak.net  Fri May 12 13:04:27 2006
From: mwh at codespeak.net (mwh at codespeak.net)
Date: Fri, 12 May 2006 13:04:27 +0200 (CEST)
Subject: [pypy-svn] r27126 - pypy/dist/pypy/translator/stackless
Message-ID: <20060512110427.5A5D6100A7@code0.codespeak.net>

Author: mwh
Date: Fri May 12 13:04:26 2006
New Revision: 27126

Modified:
   pypy/dist/pypy/translator/stackless/transform.py
Log:
add a stackless analyzer; currently it just says "yes" all the time though.


Modified: pypy/dist/pypy/translator/stackless/transform.py
==============================================================================
--- pypy/dist/pypy/translator/stackless/transform.py	(original)
+++ pypy/dist/pypy/translator/stackless/transform.py	Fri May 12 13:04:26 2006
@@ -13,6 +13,7 @@
 from pypy.rpython.rbuiltin import gen_cast
 from pypy.rpython.rtyper import LowLevelOpList
 from pypy.rpython.module import ll_stackless, ll_stack
+from pypy.translator.backendopt import graphanalyze
 
 from pypy.translator.stackless.code import STATE_HEADER, null_state
 
@@ -108,20 +109,24 @@
                                 *fields)
             self.frametypes[key] = T
         return T, fieldnames
-        
+
+class StacklessAnalyzer(graphanalyze.GraphAnalyzer):
+    def operation_is_true(self, op):
+        return True
 
 class StacklessTransformer(object):
     def __init__(self, translator, entrypoint):
         self.translator = translator
 
-        edata = translator.rtyper.getexceptiondata()
+        self.frametyper = FrameTyper()
+        self.analyzer = StacklessAnalyzer(translator)
+        self.curr_graph = None
+        
         bk = translator.annotator.bookkeeper
 
         self.unwind_exception_type = getinstancerepr(
             self.translator.rtyper,
             bk.getuniqueclassdef(code.UnwindException)).lowleveltype
-        self.frametyper = FrameTyper()
-        self.curr_graph = None
 
         mixlevelannotator = MixLevelHelperAnnotator(translator.rtyper)
         l2a = annmodel.lltype_to_annotation
@@ -200,6 +205,9 @@
         if hasattr(graph, 'func'):
             if getattr(graph.func, 'stackless_explicit', False):
                 return
+
+        if not self.analyzer.analyze_direct_call(graph):
+            return
         
         assert self.curr_graph is None
         self.curr_graph = graph


From antocuni at codespeak.net  Fri May 12 14:29:50 2006
From: antocuni at codespeak.net (antocuni at codespeak.net)
Date: Fri, 12 May 2006 14:29:50 +0200 (CEST)
Subject: [pypy-svn] r27128 - in pypy/dist/pypy/rpython: lltypesystem
	ootypesystem ootypesystem/test test
Message-ID: <20060512122950.CED5A100A9@code0.codespeak.net>

Author: antocuni
Date: Fri May 12 14:29:41 2006
New Revision: 27128

Modified:
   pypy/dist/pypy/rpython/lltypesystem/rstr.py
   pypy/dist/pypy/rpython/ootypesystem/ootype.py
   pypy/dist/pypy/rpython/ootypesystem/rstr.py
   pypy/dist/pypy/rpython/ootypesystem/test/test_oostring.py
   pypy/dist/pypy/rpython/test/test_rstr.py
Log:
More work on ootype.String:

  - String has been made a subclass of BuiltinADTType instead of
    OOType, so it can be treated as List and Dict; String will have a
    set of _METHODS corresponding to those of the RPythonic str;
    methods' name will start with 'll_' (e.g., ll_join instead of
    join);

  - _string is no longer a subclass of str; when an attribute whose
    name starts with 'll_' is accesed _string string delegates the
    implementation to its member '_str', thus avoiding writing a lot
    of boilerplate.

  - rstr.StringRepr has been enhanced; a test for ootypesystem has
    been written in test/test_rstr.py.



Modified: pypy/dist/pypy/rpython/lltypesystem/rstr.py
==============================================================================
--- pypy/dist/pypy/rpython/lltypesystem/rstr.py	(original)
+++ pypy/dist/pypy/rpython/lltypesystem/rstr.py	Fri May 12 14:29:41 2006
@@ -108,8 +108,6 @@
 #  get flowed and annotated, mostly with SomePtr.
 #
 
-# TODO: move it to a better place
-
 class LLHelpers:
     __metaclass__ = StaticMethods
 

Modified: pypy/dist/pypy/rpython/ootypesystem/ootype.py
==============================================================================
--- pypy/dist/pypy/rpython/ootypesystem/ootype.py	(original)
+++ pypy/dist/pypy/rpython/ootypesystem/ootype.py	Fri May 12 14:29:41 2006
@@ -181,16 +181,6 @@
         StaticMethod.__init__(self, args, result)
 
 
-class String(OOType):
-
-    def _defl(self):
-        return make_string("")
-    
-    def _example(self):
-        return self._defl()
-
-String = String()
-
 class BuiltinType(OOType):
 
     def _example(self):
@@ -276,6 +266,30 @@
         return self, meth
 
 
+# WARNING: the name 'String' is rebound at the end of file
+class String(BuiltinADTType):
+
+    def __init__(self):
+        self._GENERIC_METHODS = frozendict({
+            "ll_stritem_nonneg": Meth([Signed], Char),
+            "ll_stritem": Meth([Signed], Char),
+        })
+
+        self._setup_methods({})
+
+    def _defl(self):
+        return make_string("")
+    
+    def _example(self):
+        return self._defl()
+
+    def _get_interp_class(self):
+        return _string
+
+    def _specialize(self, generic_types):
+        return self
+
+
 class List(BuiltinADTType):
     # placeholders for types
     # make sure that each derived class has his own SELFTYPE_T
@@ -654,7 +668,7 @@
 
 def make_string(value):
     assert isinstance(value, str)
-    return _string(value)
+    return _string(String, value)
 
 def make_instance(INSTANCE):
     inst = _instance(INSTANCE)
@@ -738,8 +752,6 @@
        callb, checked_args = self.meth._checkargs(args)
        return callb(self.inst, *checked_args)
 
-class _string(str):
-    _TYPE = String
 
 class _builtin_type(object):
     def __getattribute__(self, name):
@@ -751,6 +763,46 @@
         return object.__getattribute__(self, name)
 
 
+
+class _string(_builtin_type):
+
+    def __init__(self, STRING, value = ''):
+        self._str = value
+        self._TYPE = STRING
+
+    def ll_stritem(self, i):
+        # NOT_RPYTHON
+        return self._str[i]
+
+    def ll_stritem_nonneg(self, i):
+        # NOT_RPYTHON
+        assert i >= 0
+        return self._str[i]
+
+    # delegate missing ll_* methods to self._str
+    def __getattr__(self, attr):
+        if attr.startswith('ll_'):
+            return self.wrapper(getattr(self._str, attr[3:]))
+        else:
+            raise AttributeError, attr
+
+    @staticmethod
+    def wrapper(fn):
+        def f(*args, **kwds):
+            res = fn(*args, **kwds)
+            if isinstance(res, str):
+                return make_string(res)
+            elif isinstance(res, list):
+                # it must be a list of strings
+                for i, item in enumerate(res):
+                    res[i] = make_string(item)
+                lst = _list(List(String))
+                lst._list = res
+                return lst
+            else:
+                return res
+        return f
+
 class _list(_builtin_type):
 
     def __init__(self, LIST):
@@ -1004,5 +1056,5 @@
 def hasDictTypes(DICT):
     return DICT._is_initialized()
 
-
+String = String()
 ROOT = Instance('Root', None, _is_root=True)

Modified: pypy/dist/pypy/rpython/ootypesystem/rstr.py
==============================================================================
--- pypy/dist/pypy/rpython/ootypesystem/rstr.py	(original)
+++ pypy/dist/pypy/rpython/ootypesystem/rstr.py	Fri May 12 14:29:41 2006
@@ -1,3 +1,4 @@
+from pypy.tool.staticmethods import StaticMethods
 from pypy.rpython.rstr import AbstractStringRepr, \
      AbstractCharRepr, AbstractUniCharRepr, AbstractStringIteratorRepr
 from pypy.rpython.lltypesystem.lltype import Ptr, Char, UniChar
@@ -23,6 +24,10 @@
 
     lowleveltype = String
 
+    def __init__(self, *args):
+        AbstractStringRepr.__init__(self, *args)
+        self.ll = LLHelpers
+
     def convert_const(self, value):
         # XXX what do we do about null strings?
         #if value is None:
@@ -41,6 +46,15 @@
 class UniCharRepr(AbstractUniCharRepr):
     lowleveltype = UniChar
 
+class LLHelpers:
+    __metaclass__ = StaticMethods
+
+    def ll_stritem_nonneg(s, i):
+        return s.ll_stritem_nonneg(i)
+
+    def ll_stritem(s, i):
+        return s.ll_stritem(i)
+
 
 string_repr = StringRepr()
 char_repr = CharRepr()

Modified: pypy/dist/pypy/rpython/ootypesystem/test/test_oostring.py
==============================================================================
--- pypy/dist/pypy/rpython/ootypesystem/test/test_oostring.py	(original)
+++ pypy/dist/pypy/rpython/ootypesystem/test/test_oostring.py	Fri May 12 14:29:41 2006
@@ -1,8 +1,20 @@
+from pypy.rpython.ootypesystem import ootype
 from pypy.rpython.test.test_llinterp import interpret 
 
 def test_constant_string():
     def f():
         return "foo"
     res = interpret(f, [], type_system="ootype")
-    assert res == "foo"
+    assert res._str == "foo"
 
+def test_builtin_method():
+    s = ootype.make_string('foo bar')
+    assert s.ll_startswith('foo') == True
+    assert s.ll_upper()._str == 'FOO BAR'
+
+def test_split():
+    s = ootype.make_string('foo bar')
+    res = s.ll_split()
+    assert isinstance(res, ootype._list)
+    assert res.ll_getitem_fast(0)._str == 'foo'
+    assert res.ll_getitem_fast(1)._str == 'bar'

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 May 12 14:29:41 2006
@@ -22,13 +22,26 @@
         res = LLHelpers.ll_rfind(llstr(s1), llstr(s2), 0, n1)
         assert res == s1.rfind(s2)
 
-def test_simple():
-    def fn(i):
-        s = 'hello'
-        return s[i]
-    for i in range(5):
-        res = interpret(fn, [i])
-        assert res == 'hello'[i]
+
+class AbstractTestRstr:
+
+    def interpret(self, fn, args):
+        return interpret(fn, args, type_system=self.ts)
+
+    def interpret_raises(self, exc, fn, args):
+        return interpret_raises(exc, fn, args, type_system=self.ts)
+
+    def _skip_oo(self, reason):
+        if self.ts == 'ootype':
+            py.test.skip("ootypesystem doesn't support %s, yet" % reason)
+
+    def test_simple(self):
+        def fn(i):
+            s = 'hello'
+            return s[i]
+        for i in range(5):
+            res = self.interpret(fn, [i])
+            assert res == 'hello'[i]
 
 def test_implicit_index_error():
     def fn(i):
@@ -564,3 +577,9 @@
     assert res._obj.value == "ello"
     res = interpret(g, [-2])
     assert res._obj.value == 42
+
+class TestLltype(AbstractTestRstr):
+    ts = "lltype"
+
+class TestOotype(AbstractTestRstr):
+    ts = "ootype"


From ac at codespeak.net  Fri May 12 16:01:03 2006
From: ac at codespeak.net (ac at codespeak.net)
Date: Fri, 12 May 2006 16:01:03 +0200 (CEST)
Subject: [pypy-svn] r27130 - in pypy/dist/pypy: rpython/rctypes
	rpython/rctypes/test translator/c translator/c/src
Message-ID: <20060512140103.B91CD100B4@code0.codespeak.net>

Author: ac
Date: Fri May 12 16:01:03 2006
New Revision: 27130

Modified:
   pypy/dist/pypy/rpython/rctypes/aprimitive.py
   pypy/dist/pypy/rpython/rctypes/rmodel.py
   pypy/dist/pypy/rpython/rctypes/rprimitive.py
   pypy/dist/pypy/rpython/rctypes/test/test_rprimitive.py
   pypy/dist/pypy/rpython/rctypes/test/test_rvoid_p.py
   pypy/dist/pypy/translator/c/primitive.py
   pypy/dist/pypy/translator/c/src/int.h
Log:
Suppport translation of ctypes integer types.
c_float and c_wchar still to go.



Modified: pypy/dist/pypy/rpython/rctypes/aprimitive.py
==============================================================================
--- pypy/dist/pypy/rpython/rctypes/aprimitive.py	(original)
+++ pypy/dist/pypy/rpython/rctypes/aprimitive.py	Fri May 12 16:01:03 2006
@@ -9,16 +9,16 @@
 ctypes_annotation_list = {
     c_char:          lltype.Char,
     c_wchar:         lltype.UniChar,
-    c_byte:          lltype.Signed,
-    c_ubyte:         lltype.Unsigned,
+    c_byte:          rcarith.CByte,
+    c_ubyte:         rcarith.CUByte,
     c_short:         rcarith.CShort,
-    c_ushort:        lltype.Unsigned,
-    c_int:           lltype.Signed,
-    c_uint:          lltype.Unsigned,
-    c_long:          lltype.Signed,
-    c_ulong:         lltype.Unsigned,
-    c_longlong:      lltype.SignedLongLong,
-    c_ulonglong:     lltype.UnsignedLongLong,
+    c_ushort:        rcarith.CUShort,
+    c_int:           rcarith.CInt,
+    c_uint:          rcarith.CUInt,
+    c_long:          rcarith.CLong,
+    c_ulong:         rcarith.CULong,
+    c_longlong:      rcarith.CLonglong,
+    c_ulonglong:     rcarith.CULonglong,
     c_float:         lltype.Float,
     c_double:        lltype.Float,
 }   # nb. platform-dependent duplicate ctypes are removed

Modified: pypy/dist/pypy/rpython/rctypes/rmodel.py
==============================================================================
--- pypy/dist/pypy/rpython/rctypes/rmodel.py	(original)
+++ pypy/dist/pypy/rpython/rctypes/rmodel.py	Fri May 12 16:01:03 2006
@@ -240,9 +240,7 @@
     def rtype_is_true(self, hop):
         [v_box] = hop.inputargs(self)
         v_value = self.getvalue(hop.llops, v_box)
-        if v_value.concretetype in (lltype.Char, lltype.UniChar):
-            llfn = ll_c_char_is_true
-        elif v_value.concretetype == llmemory.Address:
+        if v_value.concretetype == llmemory.Address:
             llfn = ll_address_is_true
         else:
             llfn = ll_is_true
@@ -253,9 +251,6 @@
 def ll_is_true(x):
     return bool(x)
 
-def ll_c_char_is_true(x):
-    return bool(ord(x))
-
 def ll_address_is_true(x):
     return x != llmemory.NULL
 

Modified: pypy/dist/pypy/rpython/rctypes/rprimitive.py
==============================================================================
--- pypy/dist/pypy/rpython/rctypes/rprimitive.py	(original)
+++ pypy/dist/pypy/rpython/rctypes/rprimitive.py	Fri May 12 16:01:03 2006
@@ -48,11 +48,25 @@
                                                         self.ll_type)
         self.setvalue(hop.llops, v_primitive, v_value)
 
+    def rtype_is_true(self, hop):
+        [v_box] = hop.inputargs(self)
+        v_value = self.return_value(hop.llops, self.getvalue(hop.llops, v_box))
+        if v_value.concretetype in (lltype.Char, lltype.UniChar):
+            llfn = ll_c_char_is_true
+        else:
+            llfn = ll_is_true
+        return hop.gendirectcall(llfn, v_value)
+
     def initialize_const(self, p, value):
         if isinstance(value, self.ctype):
             value = value.value
         p.c_data[0] = lltype.cast_primitive(self.ll_type, value)
 
+def ll_is_true(x):
+    return bool(x)
+
+def ll_c_char_is_true(x):
+    return bool(ord(x))
 
 class __extend__(pairtype(IntegerRepr, PrimitiveRepr),
                  pairtype(FloatRepr, PrimitiveRepr),

Modified: pypy/dist/pypy/rpython/rctypes/test/test_rprimitive.py
==============================================================================
--- pypy/dist/pypy/rpython/rctypes/test/test_rprimitive.py	(original)
+++ pypy/dist/pypy/rpython/rctypes/test/test_rprimitive.py	Fri May 12 16:01:03 2006
@@ -517,12 +517,21 @@
         fn = compile(access_c_float, [])
         assert fn() == 5.2
 
-    def test_compile_short(self):
-        #py.test.skip('In-progress')
-        def sizeof_c_short():
-            return sizeof(c_short)
-        fn = compile(sizeof_c_short, [])
-        assert fn() == sizeof(c_short)
+    def test_compile_c_integers(self):
+        c_integers = [c_byte, c_ubyte, c_short, c_ushort, c_int, c_uint,
+                      c_long, c_ulong, c_longlong, c_ulonglong]
+        for c_integer in c_integers:
+            def sizeof_c_integer():
+                return sizeof(c_integer)
+            fn = compile(sizeof_c_integer, [])
+            assert fn() == sizeof_c_integer()
+
+        for c_integer in c_integers:
+            def c_integer_is_unsigned(i):
+                return c_integer(-1).value > 0
+            c_integer_is_unsigned.__name__ == c_integer.__name__
+            fn = compile(c_integer_is_unsigned, [int])
+            assert fn(-1) == c_integer_is_unsigned(-1)
         
 
     def test_compile_primitive_value(self):

Modified: pypy/dist/pypy/rpython/rctypes/test/test_rvoid_p.py
==============================================================================
--- pypy/dist/pypy/rpython/rctypes/test/test_rvoid_p.py	(original)
+++ pypy/dist/pypy/rpython/rctypes/test/test_rvoid_p.py	Fri May 12 16:01:03 2006
@@ -74,7 +74,8 @@
             assert strlen(s) == 3
             assert strlen(c_char_p(s)) == 3
             assert strlen((c_char * 6)('a', 'b')) == 2
-            assert strlen((c_byte * 6)(104,101,108,108,111)) == 5
+            # XXX Bytes are not chars in llinterp.
+            # assert strlen((c_byte * 6)(104,101,108,108,111)) == 5
             buf = create_string_buffer(10)
             buf.value = "hello"
             assert strlen(buf) == 5

Modified: pypy/dist/pypy/translator/c/primitive.py
==============================================================================
--- pypy/dist/pypy/translator/c/primitive.py	(original)
+++ pypy/dist/pypy/translator/c/primitive.py	Fri May 12 16:01:03 2006
@@ -148,13 +148,16 @@
     Address:  'NULL',
     }
 
-def define_c_primitive(lltype, c_name):
-    if lltype in PrimitiveName:
+def define_c_primitive(ll_type, c_name):
+    if ll_type in PrimitiveName:
         return
-    name_str = '((%s) %%dULL)' % c_name
-    PrimitiveName[lltype] = lambda value, db: name_str % value
-    PrimitiveType[lltype] = '%s @'% c_name
-    PrimitiveErrorValue[lltype] = '((%s) -1)'% c_name
+    if ll_type._cast(-1) > 0:
+        name_str = '((%s) %%dULL)' % c_name
+    else:
+        name_str = '((%s) %%dLL)' % c_name
+    PrimitiveName[ll_type] = lambda value, db: name_str % value
+    PrimitiveType[ll_type] = '%s @'% c_name
+    PrimitiveErrorValue[ll_type] = '((%s) -1)'% c_name
     
 try:
     import ctypes
@@ -162,6 +165,19 @@
     pass
 else:
     from pypy.rpython.rctypes import rcarithmetic as rcarith
-    
-    define_c_primitive(rcarith.CShort, 'short')
+    for ll_type, c_name in [(rcarith.CByte, 'signed char'),
+                            (rcarith.CUByte, 'unsigned char'),
+                            (rcarith.CShort, 'short'),
+                            (rcarith.CUShort, 'unsigned short'),
+                            (rcarith.CInt, 'int'),
+                            (rcarith.CUInt, 'unsigned int'),
+                            (rcarith.CLong, 'long'),
+                            (rcarith.CULong, 'unsigned long'),
+                            (rcarith.CLonglong, 'long long'),
+                            (rcarith.CULonglong, 'unsigned long long')]:
+        if ll_type in PrimitiveName:
+            continue
+        PrimitiveName[ll_type] = lambda value, db, c_name=c_name: '((%s) %dULL)' % (c_name, value)
+        PrimitiveType[ll_type] = '%s @'% c_name
+        PrimitiveErrorValue[ll_type] = '((%s) -1)'% c_name
     

Modified: pypy/dist/pypy/translator/c/src/int.h
==============================================================================
--- pypy/dist/pypy/translator/c/src/int.h	(original)
+++ pypy/dist/pypy/translator/c/src/int.h	Fri May 12 16:01:03 2006
@@ -280,6 +280,7 @@
 #define OP_UINT_XOR OP_INT_XOR
 
 #define OP_ULLONG_MUL OP_INT_MUL
+#define OP_ULLONG_GT OP_INT_GT
 
 #define OP_LLONG_IS_TRUE OP_INT_IS_TRUE
 #define OP_LLONG_INVERT OP_INT_INVERT


From antocuni at codespeak.net  Fri May 12 17:01:03 2006
From: antocuni at codespeak.net (antocuni at codespeak.net)
Date: Fri, 12 May 2006 17:01:03 +0200 (CEST)
Subject: [pypy-svn] r27139 - in pypy/dist/pypy/rpython: . lltypesystem
	ootypesystem test
Message-ID: <20060512150103.A133B100B4@code0.codespeak.net>

Author: antocuni
Date: Fri May 12 17:00:53 2006
New Revision: 27139

Modified:
   pypy/dist/pypy/rpython/lltypesystem/rstr.py
   pypy/dist/pypy/rpython/ootypesystem/ootype.py
   pypy/dist/pypy/rpython/ootypesystem/rstr.py
   pypy/dist/pypy/rpython/rstr.py
   pypy/dist/pypy/rpython/test/test_rstr.py
Log:
More work on rstr:

  - Added support for null strings in ootypesystem
  
  - Part of LLHelpers has been factored out and placed in
    AbstractLLHelpers so that can be shared by the two typesystems

  - Added support for stritem, strlen, strconcat to ootypesystem

  - Some tests have been made typesystem-aware.



Modified: pypy/dist/pypy/rpython/lltypesystem/rstr.py
==============================================================================
--- pypy/dist/pypy/rpython/lltypesystem/rstr.py	(original)
+++ pypy/dist/pypy/rpython/lltypesystem/rstr.py	Fri May 12 17:00:53 2006
@@ -1,11 +1,12 @@
 from weakref import WeakValueDictionary
-from pypy.tool.staticmethods import StaticMethods
 from pypy.annotation.pairtype import pairtype
+from pypy.rpython.error import TyperError
 from pypy.rpython.robject import PyObjRepr, pyobj_repr
 from pypy.rpython.rarithmetic import _hash_string
 from pypy.rpython.rmodel import inputconst, IntegerRepr
-from pypy.rpython.rstr import AbstractStringRepr, \
-     AbstractCharRepr, AbstractUniCharRepr, AbstractStringIteratorRepr
+from pypy.rpython.rstr import AbstractStringRepr,AbstractCharRepr,\
+     AbstractUniCharRepr, AbstractStringIteratorRepr,\
+     AbstractLLHelpers
 from pypy.rpython import rint
 from pypy.rpython.lltypesystem.lltype import \
      GcStruct, Signed, Array, Char, UniChar, Ptr, malloc, \
@@ -108,41 +109,7 @@
 #  get flowed and annotated, mostly with SomePtr.
 #
 
-class LLHelpers:
-    __metaclass__ = StaticMethods
-
-    def ll_char_isspace(ch):
-        c = ord(ch) 
-        return c == 32 or (c <= 13 and c >= 9)   # c in (9, 10, 11, 12, 13, 32)
-
-    def ll_char_isdigit(ch):
-        c = ord(ch)
-        return c <= 57 and c >= 48
-
-    def ll_char_isalpha(ch):
-        c = ord(ch)
-        if c >= 97:
-            return c <= 122
-        else:
-            return 65 <= c <= 90
-
-    def ll_char_isalnum(ch):
-        c = ord(ch)
-        if c >= 65:
-            if c >= 97:
-                return c <= 122
-            else:
-                return c <= 90
-        else:
-            return 48 <= c <= 57
-
-    def ll_char_isupper(ch):
-        c = ord(ch)
-        return 65 <= c <= 90
-
-    def ll_char_islower(ch):   
-        c = ord(ch)
-        return 97 <= c <= 122
+class LLHelpers(AbstractLLHelpers):
 
     def ll_char_mul(ch, times):
         newstr = malloc(STR, times)
@@ -152,39 +119,12 @@
             j += 1
         return newstr
 
-    def ll_char_hash(ch):
-        return ord(ch)
-
-    def ll_unichar_hash(ch):
-        return ord(ch)
-
     def ll_strlen(s):
         return len(s.chars)
 
     def ll_stritem_nonneg(s, i):
         return s.chars[i]
 
-    def ll_stritem_nonneg_checked(s, i):
-        if i >= len(s.chars):
-            raise IndexError
-        return s.chars[i]
-
-    def ll_stritem(s, i):
-        if i < 0:
-            i += len(s.chars)
-        return s.chars[i]
-
-    def ll_stritem_checked(s, i):
-        if i < 0:
-            i += len(s.chars)
-        if i >= len(s.chars) or i < 0:
-            raise IndexError
-        return s.chars[i]
-
-    def ll_str_is_true(s):
-        # check if a string is True, allowing for None
-        return bool(s) and len(s.chars) != 0
-
     def ll_chr2str(ch):
         s = malloc(STR, 1)
         s.chars[0] = ch
@@ -736,7 +676,7 @@
 do_stringformat = LLHelpers.do_stringformat
 
 string_repr = StringRepr()
-char_repr   = CharRepr()
+char_repr = CharRepr()
 unichar_repr = UniCharRepr()
 char_repr.ll = LLHelpers
 unichar_repr.ll = LLHelpers

Modified: pypy/dist/pypy/rpython/ootypesystem/ootype.py
==============================================================================
--- pypy/dist/pypy/rpython/ootypesystem/ootype.py	(original)
+++ pypy/dist/pypy/rpython/ootypesystem/ootype.py	Fri May 12 17:00:53 2006
@@ -268,15 +268,20 @@
 
 # WARNING: the name 'String' is rebound at the end of file
 class String(BuiltinADTType):
+    SELFTYPE_T = object()
 
     def __init__(self):
+        self._null = _null_string(self)
+
+        generic_types = { self.SELFTYPE_T: self }
         self._GENERIC_METHODS = frozendict({
             "ll_stritem_nonneg": Meth([Signed], Char),
-            "ll_stritem": Meth([Signed], Char),
+            "ll_strlen": Meth([], Signed),
+            "ll_strconcat": Meth([self.SELFTYPE_T], self.SELFTYPE_T)
         })
+        self._setup_methods(generic_types)
 
-        self._setup_methods({})
-
+    # TODO: should it return _null or ''?
     def _defl(self):
         return make_string("")
     
@@ -770,15 +775,19 @@
         self._str = value
         self._TYPE = STRING
 
-    def ll_stritem(self, i):
-        # NOT_RPYTHON
-        return self._str[i]
-
     def ll_stritem_nonneg(self, i):
         # NOT_RPYTHON
         assert i >= 0
         return self._str[i]
 
+    def ll_strlen(self):
+        # NOT_RPYTHON
+        return len(self._str)
+
+    def ll_strconcat(self, s):
+        # NOT_RPYTHON
+        return make_string(self._str + s._str)
+
     # delegate missing ll_* methods to self._str
     def __getattr__(self, attr):
         if attr.startswith('ll_'):
@@ -803,8 +812,11 @@
                 return res
         return f
 
-class _list(_builtin_type):
+class _null_string(_null_mixin(_string), _string):
+    def __init__(self, STRING):
+        self.__dict__["_TYPE"] = STRING
 
+class _list(_builtin_type):
     def __init__(self, LIST):
         self._TYPE = LIST
         self._list = []

Modified: pypy/dist/pypy/rpython/ootypesystem/rstr.py
==============================================================================
--- pypy/dist/pypy/rpython/ootypesystem/rstr.py	(original)
+++ pypy/dist/pypy/rpython/ootypesystem/rstr.py	Fri May 12 17:00:53 2006
@@ -1,6 +1,7 @@
-from pypy.tool.staticmethods import StaticMethods
-from pypy.rpython.rstr import AbstractStringRepr, \
-     AbstractCharRepr, AbstractUniCharRepr, AbstractStringIteratorRepr
+from pypy.rpython.error import TyperError
+from pypy.rpython.rstr import AbstractStringRepr,AbstractCharRepr,\
+     AbstractUniCharRepr, AbstractStringIteratorRepr,\
+     AbstractLLHelpers
 from pypy.rpython.lltypesystem.lltype import Ptr, Char, UniChar
 from pypy.rpython.ootypesystem.ootype import Signed, Record, String, make_string
 
@@ -29,9 +30,8 @@
         self.ll = LLHelpers
 
     def convert_const(self, value):
-        # XXX what do we do about null strings?
-        #if value is None:
-        #    return nullptr(STR)
+        if value is None:
+            return String._null
         if not isinstance(value, str):
             raise TyperError("not a str: %r" % (value,))
         return make_string(value)
@@ -46,19 +46,22 @@
 class UniCharRepr(AbstractUniCharRepr):
     lowleveltype = UniChar
 
-class LLHelpers:
-    __metaclass__ = StaticMethods
+class LLHelpers(AbstractLLHelpers):
 
     def ll_stritem_nonneg(s, i):
         return s.ll_stritem_nonneg(i)
 
-    def ll_stritem(s, i):
-        return s.ll_stritem(i)
+    def ll_strlen(s):
+        return s.ll_strlen()
 
+    def ll_strconcat(s1, s2):
+        return s1.ll_strconcat(s2)
 
 string_repr = StringRepr()
 char_repr = CharRepr()
 unichar_repr = UniCharRepr()
+char_repr.ll = LLHelpers
+unichar_repr.ll = LLHelpers
 
 class StringIteratorRepr(AbstractStringIteratorRepr):
 

Modified: pypy/dist/pypy/rpython/rstr.py
==============================================================================
--- pypy/dist/pypy/rpython/rstr.py	(original)
+++ pypy/dist/pypy/rpython/rstr.py	Fri May 12 17:00:53 2006
@@ -1,3 +1,4 @@
+from pypy.tool.staticmethods import StaticMethods
 from pypy.annotation.pairtype import pairtype
 from pypy.annotation import model as annmodel
 from pypy.rpython.error import TyperError
@@ -463,3 +464,82 @@
         hop.exception_is_here()
         return hop.gendirectcall(self.ll_strnext, v_iter)
 
+
+# ____________________________________________________________
+#
+#  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.
+#
+
+# this class contains low level helpers used both by lltypesystem and
+# ootypesystem; each typesystem should subclass it and add its own
+# primitives.
+class AbstractLLHelpers:
+    __metaclass__ = StaticMethods
+
+    def ll_char_isspace(ch):
+        c = ord(ch) 
+        return c == 32 or (c <= 13 and c >= 9)   # c in (9, 10, 11, 12, 13, 32)
+
+    def ll_char_isdigit(ch):
+        c = ord(ch)
+        return c <= 57 and c >= 48
+
+    def ll_char_isalpha(ch):
+        c = ord(ch)
+        if c >= 97:
+            return c <= 122
+        else:
+            return 65 <= c <= 90
+
+    def ll_char_isalnum(ch):
+        c = ord(ch)
+        if c >= 65:
+            if c >= 97:
+                return c <= 122
+            else:
+                return c <= 90
+        else:
+            return 48 <= c <= 57
+
+    def ll_char_isupper(ch):
+        c = ord(ch)
+        return 65 <= c <= 90
+
+    def ll_char_islower(ch):   
+        c = ord(ch)
+        return 97 <= c <= 122
+
+    def ll_char_hash(ch):
+        return ord(ch)
+
+    def ll_unichar_hash(ch):
+        return ord(ch)
+
+    @classmethod
+    def ll_str_is_true(cls, s):
+        # check if a string is True, allowing for None
+        return bool(s) and cls.ll_strlen(s) != 0
+
+    @classmethod
+    def ll_stritem_nonneg_checked(cls, s, i):
+        if i >= cls.ll_strlen(s):
+            raise IndexError
+        return cls.ll_stritem_nonneg(s, i)
+
+    @classmethod
+    def ll_stritem(cls, s, i):
+        if i < 0:
+            i += cls.ll_strlen(s)
+        return cls.ll_stritem_nonneg(s, i)
+
+    @classmethod
+    def ll_stritem_checked(cls, s, i):
+        length = cls.ll_strlen(s)
+        if i < 0:
+            i += length
+        if i >= length or i < 0:
+            raise IndexError
+        return cls.ll_stritem_nonneg(s, i)
+

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 May 12 17:00:53 2006
@@ -43,59 +43,46 @@
             res = self.interpret(fn, [i])
             assert res == 'hello'[i]
 
-def test_implicit_index_error():
-    def fn(i):
-        s = 'hello'
-        try:
-            return s[i]
-        except IndexError:
-            return '*'
-    for i in range(-5, 5):
-        res = interpret(fn, [i])
-        assert res == 'hello'[i]
-    res = interpret(fn, [5])
-    assert res == '*'
-    res = interpret(fn, [6])
-    assert res == '*'
-    res = interpret(fn, [-42])
-    assert res == '*'
-    
-
-def test_nonzero():
-    def fn(i, j):
-        s = ['', 'xx'][j]
-        if i < 0:
-            s = None
-        if i > -2:
-            return bool(s)
-        else:
-            return False
-    for i in [-2, -1, 0]:
-        for j in range(2):
-            res = interpret(fn, [i, j])
-            assert res is fn(i, j)
-
-def test_hash():
-    def fn(i):
-        if i == 0:
-            s = ''
-        else:
-            s = "xxx"
-        return hash(s)
-    res = interpret(fn, [0])
-    assert res == -1
-    res = interpret(fn, [1])
-    assert typeOf(res) == Signed
-
-def test_concat():
-    def fn(i, j):
-        s1 = ['', 'a', 'ab']
-        s2 = ['', 'x', 'xy']
-        return s1[i] + s2[j]
-    for i in range(3):
-        for j in range(3):
-            res = interpret(fn, [i,j])
-            assert ''.join(res.chars) == fn(i, j)
+    def test_implicit_index_error(self):
+        def fn(i):
+            s = 'hello'
+            try:
+                return s[i]
+            except IndexError:
+                return '*'
+        for i in range(-5, 5):
+            res = self.interpret(fn, [i])
+            assert res == 'hello'[i]
+        res = self.interpret(fn, [5])
+        assert res == '*'
+        res = self.interpret(fn, [6])
+        assert res == '*'
+        res = self.interpret(fn, [-42])
+        assert res == '*'
+
+    def test_nonzero(self):
+        def fn(i, j):
+            s = ['', 'xx'][j]
+            if i < 0:
+                s = None
+            if i > -2:
+                return bool(s)
+            else:
+                return False
+        for i in [-2, -1, 0]:
+            for j in range(2):
+                res = self.interpret(fn, [i, j])
+                assert res is fn(i, j)
+
+    def test_concat(self):
+        def fn(i, j):
+            s1 = ['', 'a', 'ab']
+            s2 = ['', 'x', 'xy']
+            return s1[i] + s2[j]
+        for i in range(3):
+            for j in range(3):
+                res = self.interpret(fn, [i,j])
+                assert self.ll_to_string(res) == fn(i, j)
 
 def test_iter():
     def fn(i):
@@ -581,5 +568,24 @@
 class TestLltype(AbstractTestRstr):
     ts = "lltype"
 
+    def ll_to_string(self, s):
+        return ''.join(s.chars)
+
+    def test_hash(self):
+        def fn(i):
+            if i == 0:
+                s = ''
+            else:
+                s = "xxx"
+            return hash(s)
+        res = self.interpret(fn, [0])
+        assert res == -1
+        res = self.interpret(fn, [1])
+        assert typeOf(res) == Signed
+
+
 class TestOotype(AbstractTestRstr):
     ts = "ootype"
+
+    def ll_to_string(self, s):
+        return s._str


From mwh at codespeak.net  Fri May 12 17:26:52 2006
From: mwh at codespeak.net (mwh at codespeak.net)
Date: Fri, 12 May 2006 17:26:52 +0200 (CEST)
Subject: [pypy-svn] r27140 - pypy/dist/pypy/translator/goal
Message-ID: <20060512152652.C7D8F100B8@code0.codespeak.net>

Author: mwh
Date: Fri May 12 17:26:50 2006
New Revision: 27140

Modified:
   pypy/dist/pypy/translator/goal/targetpypystandalone.py
Log:
--new-stackless doesn't need that much memory, it turns out.


Modified: pypy/dist/pypy/translator/goal/targetpypystandalone.py
==============================================================================
--- pypy/dist/pypy/translator/goal/targetpypystandalone.py	(original)
+++ pypy/dist/pypy/translator/goal/targetpypystandalone.py	Fri May 12 17:26:50 2006
@@ -93,8 +93,6 @@
         # thread might appear twice now, but the objspace can handle this
         usemodules.append('thread')
     if options.stackless:
-        if options.stackless != 'old':
-            raise MemoryError("in-progress; might consume tons of memory")
         usemodules.append('stackless')
         
     space = StdObjSpace(nofaking=True,


From mwh at codespeak.net  Fri May 12 17:31:42 2006
From: mwh at codespeak.net (mwh at codespeak.net)
Date: Fri, 12 May 2006 17:31:42 +0200 (CEST)
Subject: [pypy-svn] r27142 - in pypy/dist/pypy/translator: backendopt
	stackless stackless/test
Message-ID: <20060512153142.D5041100B8@code0.codespeak.net>

Author: mwh
Date: Fri May 12 17:31:41 2006
New Revision: 27142

Modified:
   pypy/dist/pypy/translator/backendopt/graphanalyze.py
   pypy/dist/pypy/translator/stackless/test/test_transform.py
   pypy/dist/pypy/translator/stackless/transform.py
Log:
don't stackless transform graphs that don't need it, and don't protect calls to
such graphs.


Modified: pypy/dist/pypy/translator/backendopt/graphanalyze.py
==============================================================================
--- pypy/dist/pypy/translator/backendopt/graphanalyze.py	(original)
+++ pypy/dist/pypy/translator/backendopt/graphanalyze.py	Fri May 12 17:31:41 2006
@@ -20,13 +20,19 @@
     def analyze_startblock(self, block, seen=None):
         return False
 
+    def analyze_external_call(self, op):
+        return True
+
+    def analyze_link(self, graph, link):
+        return False
+
     # general methods
 
     def analyze(self, op, seen=None):
         if op.opname == "direct_call":
             graph = get_graph(op.args[0], self.translator)
             if graph is None:
-                return True
+                return self.analyze_external_call(op)
             return self.analyze_direct_call(graph, seen)
         elif op.opname == "indirect_call":
             if op.args[-1].value is None:
@@ -58,6 +64,9 @@
                 if self.analyze(op, seen):
                     self.analyzed_calls[graph] = True
                     return True
+            for exit in block.exits:
+                if self.analyze_link(graph, exit):
+                    return True
         self.analyzed_calls[graph] = False
         return False
 

Modified: pypy/dist/pypy/translator/stackless/test/test_transform.py
==============================================================================
--- pypy/dist/pypy/translator/stackless/test/test_transform.py	(original)
+++ pypy/dist/pypy/translator/stackless/test/test_transform.py	Fri May 12 17:31:41 2006
@@ -205,6 +205,27 @@
     res = llinterp_stackless_function(f)
     assert res == 106
 
+def test_dont_transform_too_much():
+    def check(x):
+        if x:
+            raise code.UnwindException
+    check.stackless_explicit = True
+    def f(x):
+        return x + 2
+    def g(x):
+        check(x)
+        return f(x) + x + 1
+    def example():
+        return g(one()) + 1
+    res, t = llinterp_stackless_function(example, returntranslator=True)
+    assert res == 6
+
+    ggraph = graphof(t, g)
+    for block, op in ggraph.iterblockops():
+        if op.opname == 'direct_call':
+            if op.args[0].value._obj._callable is f:
+                assert op != block.operations[-1]
+
 def rtype_stackless_function(fn):
     s_list_of_strings = annmodel.SomeList(ListDef(None, annmodel.SomeString()))
     s_list_of_strings.listdef.resize()
@@ -241,7 +262,7 @@
     res = cbuilder.cmdexec('')
     return int(res.strip())
 
-def llinterp_stackless_function(fn):
+def llinterp_stackless_function(fn, returntranslator=False):
     def wrapper(argv):
         return fn()
     t = rtype_stackless_function(wrapper)
@@ -256,4 +277,7 @@
     ll_list = r_list_of_strings.convert_const([''])
     interp = llinterp.LLInterpreter(t.rtyper)
     res = interp.eval_graph(graph, [ll_list])
-    return res
+    if returntranslator:
+        return res, t
+    else:
+        return res

Modified: pypy/dist/pypy/translator/stackless/transform.py
==============================================================================
--- pypy/dist/pypy/translator/stackless/transform.py	(original)
+++ pypy/dist/pypy/translator/stackless/transform.py	Fri May 12 17:31:41 2006
@@ -111,15 +111,35 @@
         return T, fieldnames
 
 class StacklessAnalyzer(graphanalyze.GraphAnalyzer):
+    def __init__(self, translator, unwindtype):
+        graphanalyze.GraphAnalyzer.__init__(self, translator)
+        self.unwindtype = unwindtype
+
     def operation_is_true(self, op):
-        return True
+        return op.opname == 'yield_current_frame_to_caller'
+
+    def analyze_link(self, graph, link):
+        if link.target is graph.exceptblock:
+            # XXX is this the right way to do this?
+            op = link.prevblock.operations[-1]
+            if op.opname == 'cast_pointer':
+                ct = op.args[0].concretetype
+                return ct is self.unwindtype
+        return False
+
+    def analyze_external_call(self, op):
+        callable = op.args[0].value._obj._callable
+        #assert getattr(callable, 'suggested_primitive', False)
+        return callable in [ll_stack.ll_stack_unwind,
+                            ll_stackless.ll_stackless_stack_frames_depth,
+                            ll_stackless.ll_stackless_switch]
+                            
 
 class StacklessTransformer(object):
     def __init__(self, translator, entrypoint):
         self.translator = translator
 
         self.frametyper = FrameTyper()
-        self.analyzer = StacklessAnalyzer(translator)
         self.curr_graph = None
         
         bk = translator.annotator.bookkeeper
@@ -127,6 +147,8 @@
         self.unwind_exception_type = getinstancerepr(
             self.translator.rtyper,
             bk.getuniqueclassdef(code.UnwindException)).lowleveltype
+        self.analyzer = StacklessAnalyzer(translator,
+                                          self.unwind_exception_type)
 
         mixlevelannotator = MixLevelHelperAnnotator(translator.rtyper)
         l2a = annmodel.lltype_to_annotation
@@ -363,6 +385,10 @@
                     if func in self.suggested_primitives:
                         op = replace_with_call(self.suggested_primitives[func])
 
+                if not self.analyzer.analyze(op):
+                    i += 1
+                    continue
+
                 if i == len(block.operations) - 1 \
                        and block.exitswitch == model.c_last_exception:
                     link = block.exits[0]


From pedronis at codespeak.net  Fri May 12 18:35:42 2006
From: pedronis at codespeak.net (pedronis at codespeak.net)
Date: Fri, 12 May 2006 18:35:42 +0200 (CEST)
Subject: [pypy-svn] r27144 - in pypy/dist/pypy/annotation: . test
Message-ID: <20060512163542.72A6B100C0@code0.codespeak.net>

Author: pedronis
Date: Fri May 12 18:35:40 2006
New Revision: 27144

Modified:
   pypy/dist/pypy/annotation/binaryop.py
   pypy/dist/pypy/annotation/test/test_annrpython.py
Log:
generalize integer comparison logic to cope with general bit sizes



Modified: pypy/dist/pypy/annotation/binaryop.py
==============================================================================
--- pypy/dist/pypy/annotation/binaryop.py	(original)
+++ pypy/dist/pypy/annotation/binaryop.py	Fri May 12 18:35:40 2006
@@ -193,7 +193,7 @@
 
             bind(obj2, obj1, 0)
             bind(obj1, obj2, 1)
-                
+
         return r
 
     def divmod((obj1, obj2)):
@@ -212,7 +212,7 @@
         else:
             return obj
 
-    
+
 # cloning a function with identical code, for the can_only_throw attribute
 def _clone(f, can_only_throw = None):
     newfunc = type(f)(f.func_code, f.func_globals, f.func_name,
@@ -279,14 +279,19 @@
         op = block.operations[i]
         assert op.opname == opname
         assert len(op.args) == 2
+        def tointtype(int0):
+            if int1.knowntype is bool:
+                return int
+            return int0.knowntype
         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, unsigned=int2.unsigned))
+                              SomeInteger(nonneg=True, knowntype=tointtype(int2)))
         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, unsigned=int1.unsigned))
+                              SomeInteger(nonneg=True, knowntype=tointtype(int1)))
         if knowntypedata:
             r.knowntypedata = knowntypedata
         return r

Modified: pypy/dist/pypy/annotation/test/test_annrpython.py
==============================================================================
--- pypy/dist/pypy/annotation/test/test_annrpython.py	(original)
+++ pypy/dist/pypy/annotation/test/test_annrpython.py	Fri May 12 18:35:40 2006
@@ -1303,6 +1303,25 @@
         s = a.build_types(f, [int]*8)
         assert s == annmodel.SomeTuple([annmodel.SomeInteger(nonneg=True)] * 8)
 
+    def test_general_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, [r_longlong]*8)
+        assert s == annmodel.SomeTuple([annmodel.SomeInteger(nonneg=True, knowntype=r_longlong)] * 8)
+
+
     def test_more_nonneg_cleverness(self):
         def f(start, stop):
             assert 0 <= start <= stop
@@ -1311,6 +1330,14 @@
         s = a.build_types(f, [int, int])
         assert s == annmodel.SomeTuple([annmodel.SomeInteger(nonneg=True)] * 2)
 
+    def test_more_general_nonneg_cleverness(self):
+        def f(start, stop):
+            assert 0 <= start <= stop
+            return start, stop
+        a = self.RPythonAnnotator()
+        s = a.build_types(f, [r_longlong, r_longlong])
+        assert s == annmodel.SomeTuple([annmodel.SomeInteger(nonneg=True, knowntype=r_longlong)] * 2)
+
     def test_nonneg_cleverness_is_gentle_with_unsigned(self):
         def witness1(x):
             pass
@@ -1328,7 +1355,23 @@
         assert a.binding(wg1.getargs()[0]).unsigned is True
         assert a.binding(wg2.getargs()[0]).unsigned is True        
         
-
+    def test_general_nonneg_cleverness_is_gentle_with_unsigned(self):
+        def witness1(x):
+            pass
+        def witness2(x):
+            pass        
+        def f(x):
+            if 0 < x:
+                witness1(x)
+            if x > 0:
+                witness2(x)
+        a = self.RPythonAnnotator()
+        s = a.build_types(f, [annmodel.SomeInteger(knowntype=r_ulonglong)])
+        wg1 = graphof(a, witness1)
+        wg2 = graphof(a, witness2)        
+        assert a.binding(wg1.getargs()[0]).knowntype is r_ulonglong
+        assert a.binding(wg2.getargs()[0]).knowntype is r_ulonglong
+    
     def test_attr_moving_into_parent(self):
         class A: pass
         class B(A): pass


From arigo at codespeak.net  Fri May 12 19:28:44 2006
From: arigo at codespeak.net (arigo at codespeak.net)
Date: Fri, 12 May 2006 19:28:44 +0200 (CEST)
Subject: [pypy-svn] r27151 - in pypy/dist/pypy: annotation rpython
	rpython/lltypesystem rpython/memory rpython/memory/test rpython/test
Message-ID: <20060512172844.9904D100BA@code0.codespeak.net>

Author: arigo
Date: Fri May 12 19:28:41 2006
New Revision: 27151

Modified:
   pypy/dist/pypy/annotation/bookkeeper.py
   pypy/dist/pypy/rpython/lltypesystem/llmemory.py
   pypy/dist/pypy/rpython/memory/gc.py
   pypy/dist/pypy/rpython/memory/lladdress.py
   pypy/dist/pypy/rpython/memory/test/test_address.py
   pypy/dist/pypy/rpython/objectmodel.py
   pypy/dist/pypy/rpython/raddress.py
   pypy/dist/pypy/rpython/test/test_rptr.py
Log:
Finally get rid of the two NULL addresses.  While I was at it, I renamed
lladdress.address to lladdress._address.



Modified: pypy/dist/pypy/annotation/bookkeeper.py
==============================================================================
--- pypy/dist/pypy/annotation/bookkeeper.py	(original)
+++ pypy/dist/pypy/annotation/bookkeeper.py	Fri May 12 19:28:41 2006
@@ -363,11 +363,8 @@
             result = SomeExternalObject(tp)
         elif isinstance(x, lltype._ptr):
             result = SomePtr(lltype.typeOf(x))
-        elif isinstance(x, lladdress.address):
-            assert x is lladdress.NULL
-            result= SomeAddress(is_null=True)
         elif isinstance(x, llmemory.fakeaddress):
-            result = SomeAddress()
+            result = SomeAddress(is_null=not x)
         elif isinstance(x, ootype._static_meth):
             result = SomeOOStaticMeth(ootype.typeOf(x))
         elif isinstance(x, ootype._class):

Modified: pypy/dist/pypy/rpython/lltypesystem/llmemory.py
==============================================================================
--- pypy/dist/pypy/rpython/lltypesystem/llmemory.py	(original)
+++ pypy/dist/pypy/rpython/lltypesystem/llmemory.py	Fri May 12 19:28:41 2006
@@ -166,7 +166,7 @@
 
 class fakeaddress(object):
     def __init__(self, ob, offset=None):
-        self.ob = ob
+        self.ob = ob or None    # replace null pointers with None
         self.offset = offset
 
     def __repr__(self):
@@ -206,6 +206,8 @@
         return not (self == other)
 
     def ref(self):
+        if not self:
+            raise NullAddressError
         ref = _obref(self.ob)
         if self.offset is not None:
             ref = self.offset.ref(ref)
@@ -241,11 +243,18 @@
             return lltype.cast_pointer(EXPECTED_TYPE, ref.get())
 
     def _cast_to_int(self):
-        return self.get()._cast_to_int()
+        if self:
+            return self.get()._cast_to_int()
+        else:
+            return 0
 
 # ____________________________________________________________
 
-NULL = fakeaddress(None) # XXX this should be the same as memory.lladdress.NULL
+class NullAddressError(Exception):
+    pass
+
+NULL = fakeaddress(None)
+NULL.intaddress = 0      # this is to make memory.lladdress more happy
 Address = lltype.Primitive("Address", NULL)
 
 

Modified: pypy/dist/pypy/rpython/memory/gc.py
==============================================================================
--- pypy/dist/pypy/rpython/memory/gc.py	(original)
+++ pypy/dist/pypy/rpython/memory/gc.py	Fri May 12 19:28:41 2006
@@ -1,5 +1,5 @@
 from pypy.rpython.memory.lladdress import raw_malloc, raw_free, raw_memcopy
-from pypy.rpython.memory.lladdress import NULL, address
+from pypy.rpython.memory.lladdress import NULL, _address
 from pypy.rpython.memory.support import get_address_linked_list
 from pypy.rpython.memory import lltypesimulation
 from pypy.rpython.lltypesystem import lltype, llmemory

Modified: pypy/dist/pypy/rpython/memory/lladdress.py
==============================================================================
--- pypy/dist/pypy/rpython/memory/lladdress.py	(original)
+++ pypy/dist/pypy/rpython/memory/lladdress.py	Fri May 12 19:28:41 2006
@@ -6,39 +6,34 @@
 from pypy.rpython.memory.lltypelayout import convert_offset_to_int
 from pypy.rpython.objectmodel import ComputedIntSymbolic
 
-class address(object):
-    #XXX should be _address!
-    
+NULL = llmemory.NULL
+
+
+class _address(object):
+
     def __new__(cls, intaddress=0):
         if intaddress == 0:
-            null = cls.__dict__.get("NULL")
-            if null is not None:
-                return null
-            cls.NULL = object.__new__(cls)
-            return cls.NULL
+            return NULL
         else:
             return object.__new__(cls)
 
     def __init__(self, intaddress=0):
         self.intaddress = intaddress
 
-    def _getintattr(self): #needed to make _accessor easy
-        return self.intaddress
-
     def __add__(self, offset):
         if isinstance(offset, int):
-            return address(self.intaddress + offset)
+            return _address(self.intaddress + offset)
         else:
             assert isinstance(offset, llmemory.AddressOffset)
-            return address(self.intaddress + convert_offset_to_int(offset))
+            return _address(self.intaddress + convert_offset_to_int(offset))
 
     def __sub__(self, other):
         if isinstance(other, int):
-            return address(self.intaddress - other)
+            return _address(self.intaddress - other)
         elif isinstance(other, llmemory.AddressOffset):
-            return address(self.intaddress - convert_offset_to_int(other))
+            return _address(self.intaddress - convert_offset_to_int(other))
         else:
-            assert isinstance(other, address)
+            assert isinstance(other, _address)
             return self.intaddress - other.intaddress
 
     def __cmp__(self, other):
@@ -112,20 +107,19 @@
 class _address_accessor(_accessor):
     format = "P"
     size = struct.calcsize("P")
-    convert_from = address
-    convert_to = address._getintattr
+    convert_from = _address
+    convert_to = staticmethod(lambda addr: addr.intaddress)
 
 
-address.signed = property(_signed_accessor)
-address.unsigned = property(_unsigned_accessor)
-address.char = property(_char_accessor)
-address.address = property(_address_accessor)
+_address.signed = property(_signed_accessor)
+_address.unsigned = property(_unsigned_accessor)
+_address.char = property(_char_accessor)
+_address.address = property(_address_accessor)
 
-NULL = address()
 simulator = MemorySimulator()
 
 def raw_malloc(size):
-    return address(simulator.malloc(size))
+    return _address(simulator.malloc(size))
 
 def raw_free(addr):
     simulator.free(addr.intaddress)
@@ -134,12 +128,12 @@
     simulator.memcopy(addr1.intaddress, addr2.intaddress, size)
 
 def get_address_of_object(obj):
-    return address(simulator.get_address_of_object(obj))
+    return _address(simulator.get_address_of_object(obj))
 
 def get_py_object(address):
     return simulator.get_py_object(address.intaddress)
 
-address._TYPE = llmemory.Address
+_address._TYPE = llmemory.Address
 
 supported_access_types = {"signed":    lltype.Signed,
                           "unsigned":  lltype.Unsigned,

Modified: pypy/dist/pypy/rpython/memory/test/test_address.py
==============================================================================
--- pypy/dist/pypy/rpython/memory/test/test_address.py	(original)
+++ pypy/dist/pypy/rpython/memory/test/test_address.py	Fri May 12 19:28:41 2006
@@ -6,10 +6,10 @@
 from pypy.translator.translator import graphof
 from pypy.objspace.flow import FlowObjSpace
 from pypy.rpython.rtyper import RPythonTyper
-from pypy.rpython.memory.lladdress import address, NULL
+from pypy.rpython.memory.lladdress import _address, NULL
 from pypy.rpython.memory.lladdress import raw_malloc, raw_free, raw_memcopy
 from pypy.rpython.memory.lladdress import get_py_object, get_address_of_object
-from pypy.rpython.lltypesystem.llmemory import Address
+from pypy.rpython.lltypesystem.llmemory import Address, NullAddressError
 from pypy.rpython.memory.simulator import MemorySimulatorError
 from pypy.rpython.memory.test.test_llinterpsim import interpret
 from pypy.rpython.lltypesystem import lltype
@@ -101,17 +101,17 @@
         assert isinstance(s, annmodel.SomeChar)
         assert f(0, "c") == "c"
         assert f(123, "c") == "c"
-        
 
-    def test_address_comparison(self):
-        def f(offset):
-            return NULL < NULL + offset
-        a = RPythonAnnotator()
-        s = a.build_types(f, [annmodel.SomeInteger()])
-        assert isinstance(s, annmodel.SomeBool)
-        assert f(1)
-        assert not f(0)
-        assert not f(-1)
+##    -- no longer valid since NULL is not a regular _address any more
+##    def test_address_comparison(self):
+##        def f(offset):
+##            return NULL < NULL + offset
+##        a = RPythonAnnotator()
+##        s = a.build_types(f, [annmodel.SomeInteger()])
+##        assert isinstance(s, annmodel.SomeBool)
+##        assert f(1)
+##        assert not f(0)
+##        assert not f(-1)
 
     def test_simple_offsetof(self):
         from pypy.rpython.lltypesystem import lltype
@@ -298,7 +298,7 @@
             return bool(addr)
         res = interpret(f, [NULL])
         assert isinstance(res, bool) and not res
-        res = interpret(f, [address(1)])
+        res = interpret(f, [_address(1)])
         assert isinstance(res, bool) and res
 
     def test_memory_access(self):
@@ -337,13 +337,14 @@
         assert res == "x"
 
     def test_address_comparison(self):
-        def f(offset):
-            return NULL < NULL + offset or NULL == NULL + offset
-        res = interpret(f, [10])
+        def f(addr, offset):
+            return addr < addr + offset or addr == addr + offset
+        addr = _address(129820)
+        res = interpret(f, [addr, 10])
         assert res
-        res = interpret(f, [-10])
+        res = interpret(f, [addr, -10])
         assert not res
-        res = interpret(f, [0])
+        res = interpret(f, [addr, 0])
         assert res
 
     def test_raw_memcopy(self):
@@ -363,15 +364,15 @@
 
 class TestAddressSimulation(object):
     def test_null_is_singleton(self):
-        assert address() is NULL
-        assert address() is address(0)
+        assert _address() is NULL
+        assert _address() is _address(0)
 
     def test_convert_to_bool(self):
-        assert not address()
+        assert not _address()
         assert not NULL
-        assert address(1)
-        assert address(2)
-        assert bool(address(3))
+        assert _address(1)
+        assert _address(2)
+        assert bool(_address(3))
 
     def test_memory_access(self):
         addr = raw_malloc(1000)
@@ -379,7 +380,7 @@
         assert addr.unsigned[0] == sys.maxint * 2 + 1
         addr.address[0] = addr
         assert addr.address[0] == addr
-        py.test.raises(MemorySimulatorError, "NULL.signed[0]")
+        py.test.raises(NullAddressError, "NULL.signed[0]")
 
     def test_pointer_arithmetic(self):
         addr = raw_malloc(100)

Modified: pypy/dist/pypy/rpython/objectmodel.py
==============================================================================
--- pypy/dist/pypy/rpython/objectmodel.py	(original)
+++ pypy/dist/pypy/rpython/objectmodel.py	Fri May 12 19:28:41 2006
@@ -63,9 +63,9 @@
     return fakeaddress(weakref.ref(obj))
 
 def cast_address_to_object(address, expected_result):
-    wref = address.ref().get()
-    if wref is None: # NULL address
+    if not address:  # NULL address
         return None
+    wref = address.ref().get()
     obj = wref()
     assert obj is not None
     assert isinstance(obj, expected_result)

Modified: pypy/dist/pypy/rpython/raddress.py
==============================================================================
--- pypy/dist/pypy/rpython/raddress.py	(original)
+++ pypy/dist/pypy/rpython/raddress.py	Fri May 12 19:28:41 2006
@@ -1,8 +1,8 @@
 # rtyping of memory address operations
 from pypy.annotation.pairtype import pairtype
 from pypy.annotation import model as annmodel
-from pypy.rpython.memory.lladdress import NULL, address
-from pypy.rpython.lltypesystem.llmemory import Address, cast_adr_to_int
+from pypy.rpython.memory.lladdress import _address
+from pypy.rpython.lltypesystem.llmemory import NULL, Address, cast_adr_to_int
 from pypy.rpython.rmodel import Repr, IntegerRepr
 from pypy.rpython.rptr import PtrRepr
 from pypy.rpython.lltypesystem import lltype
@@ -25,7 +25,7 @@
     lowleveltype = Address
 
     def convert_const(self, value):
-        assert not isinstance(value, address) or value is NULL
+        assert not isinstance(value, _address)
         return value
 
     def rtype_getattr(self, hop):

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	Fri May 12 19:28:41 2006
@@ -1,6 +1,7 @@
 from pypy.annotation.annrpython import RPythonAnnotator
 from pypy.rpython.annlowlevel import annotate_lowlevel_helper, LowLevelAnnotatorPolicy
 from pypy.rpython.lltypesystem.lltype import *
+from pypy.rpython.lltypesystem import llmemory
 from pypy.rpython.rtyper import RPythonTyper
 from pypy.annotation import model as annmodel
 
@@ -141,3 +142,21 @@
         return p1 == s1
     res = interpret(fn1, [])
     assert res is True
+
+def test_address():
+    S = GcStruct('S')
+    p1 = nullptr(S)
+    p2 = malloc(S)
+    
+    def g(p):
+        return bool(llmemory.cast_ptr_to_adr(p))
+    def fn(n):
+        if n < 0:
+            return g(p1)
+        else:
+            return g(p2)
+
+    res = interpret(fn, [-5])
+    assert res is False
+    res = interpret(fn, [5])
+    assert res is True


From arigo at codespeak.net  Fri May 12 20:12:28 2006
From: arigo at codespeak.net (arigo at codespeak.net)
Date: Fri, 12 May 2006 20:12:28 +0200 (CEST)
Subject: [pypy-svn] r27152 - pypy/dist/pypy/translator/goal
Message-ID: <20060512181228.C0A4F100BC@code0.codespeak.net>

Author: arigo
Date: Fri May 12 20:12:27 2006
New Revision: 27152

Modified:
   pypy/dist/pypy/translator/goal/translate.py
Log:
A '[default]' trying to be too clever, and showing on the --stackless
option.  Changed the condition to the obvious but possibly naive one.
The current translate.py at least doesn't show another case where
'[default]' should appear but no longer does because of this change.



Modified: pypy/dist/pypy/translator/goal/translate.py
==============================================================================
--- pypy/dist/pypy/translator/goal/translate.py	(original)
+++ pypy/dist/pypy/translator/goal/translate.py	Fri May 12 20:12:27 2006
@@ -135,7 +135,7 @@
             if val is None:
                 pass
             elif isinstance(val, bool):
-                if bool(val) == (option.action=="store_true"):
+                if val is True and option.action=="store_true":
                     defl = "[default]"
             else:
                 defl = "[default: %s]" % val


From arigo at codespeak.net  Fri May 12 20:13:10 2006
From: arigo at codespeak.net (arigo at codespeak.net)
Date: Fri, 12 May 2006 20:13:10 +0200 (CEST)
Subject: [pypy-svn] r27153 - in pypy/dist/pypy: annotation rpython
	rpython/lltypesystem rpython/memory rpython/module translator
	translator/c translator/c/test translator/js translator/llvm
	translator/pyrex translator/stackless
Message-ID: <20060512181310.5F6EA100C4@code0.codespeak.net>

Author: arigo
Date: Fri May 12 20:13:02 2006
New Revision: 27153

Added:
   pypy/dist/pypy/translator/stackless/frame.py   (contents, props changed)
Modified:
   pypy/dist/pypy/annotation/description.py
   pypy/dist/pypy/rpython/extfunctable.py
   pypy/dist/pypy/rpython/lltypesystem/rclass.py
   pypy/dist/pypy/rpython/memory/gcwrapper.py
   pypy/dist/pypy/rpython/module/ll_stackless.py
   pypy/dist/pypy/rpython/rstack.py
   pypy/dist/pypy/translator/c/database.py
   pypy/dist/pypy/translator/c/genc.py
   pypy/dist/pypy/translator/c/pyobj.py
   pypy/dist/pypy/translator/c/test/test_database.py
   pypy/dist/pypy/translator/c/wrapper.py
   pypy/dist/pypy/translator/driver.py
   pypy/dist/pypy/translator/js/js.py
   pypy/dist/pypy/translator/llvm/genllvm.py
   pypy/dist/pypy/translator/pyrex/genpyrex.py
   pypy/dist/pypy/translator/stackless/code.py
   pypy/dist/pypy/translator/stackless/transform.py
Log:
* Clean-up of stackless transform; split code.py in two files;
  build compressed tables instead of having multiple fields in each
  frame header; use -1 instead of 0 as the non-resuming case so that
  the table entries computation can be 0-based

* Added a .clone method() on the RPython frame types, not implemented 
  yet.

* Replaced all abuses of "bookkeeper.getdesc(func).cachedgraph(None)"
  in the PyPy sources with a new method .getuniquegraph(), which asserts
  that there is exactly one graph and returns it, no matter under what
  key.  Indeed, cachedgraph() could also build and return a fresh graph,
  with was utterly confusing the later stages of the translation 
  process.


Modified: pypy/dist/pypy/annotation/description.py
==============================================================================
--- pypy/dist/pypy/annotation/description.py	(original)
+++ pypy/dist/pypy/annotation/description.py	Fri May 12 20:13:02 2006
@@ -191,6 +191,10 @@
             graph.name = alt_name
         return graph
 
+    def getuniquegraph(self):
+        assert len(self._cache) == 1
+        return self._cache.values()[0]
+
     def cachedgraph(self, key, alt_name=None, builder=None):
         try:
             return self._cache[key]

Modified: pypy/dist/pypy/rpython/extfunctable.py
==============================================================================
--- pypy/dist/pypy/rpython/extfunctable.py	(original)
+++ pypy/dist/pypy/rpython/extfunctable.py	Fri May 12 20:13:02 2006
@@ -253,7 +253,9 @@
 declare(rstack.stack_unwind, noneannotation, 'll_stack/unwind')
 frametop_type_info = declaregcptrtype(rstack.frame_stack_top,'frame_stack_top',
                                         switch = (rstack.frame_stack_top,
-                                                  'll_stackless/switch'))
+                                                  'll_stackless/switch'),
+                                        clone  = (rstack.frame_stack_top,
+                                                  'll_stackless/clone'))
 
 # ___________________________________________________________
 # javascript

Modified: pypy/dist/pypy/rpython/lltypesystem/rclass.py
==============================================================================
--- pypy/dist/pypy/rpython/lltypesystem/rclass.py	(original)
+++ pypy/dist/pypy/rpython/lltypesystem/rclass.py	Fri May 12 20:13:02 2006
@@ -364,7 +364,7 @@
                 source_repr = getinstancerepr(self.rtyper, source_classdef)
                 assert len(s_func.descriptions) == 1
                 funcdesc = s_func.descriptions.keys()[0]
-                graph = funcdesc.cachedgraph(None)
+                graph = funcdesc.getuniquegraph()
                 FUNCTYPE = FuncType([Ptr(source_repr.object_type)], Void)
                 destrptr = functionptr(FUNCTYPE, graph.name,
                                        graph=graph,

Modified: pypy/dist/pypy/rpython/memory/gcwrapper.py
==============================================================================
--- pypy/dist/pypy/rpython/memory/gcwrapper.py	(original)
+++ pypy/dist/pypy/rpython/memory/gcwrapper.py	Fri May 12 20:13:02 2006
@@ -163,7 +163,7 @@
     
 def getfunctionptr(annotator, graphfunc):
     """Make a functionptr from the given Python function."""
-    graph = annotator.bookkeeper.getdesc(graphfunc).cachedgraph(None)
+    graph = annotator.bookkeeper.getdesc(graphfunc).getuniquegraph()
     llinputs = [v.concretetype for v in graph.getargs()]
     lloutput = graph.getreturnvar().concretetype
     FT = lltype.FuncType(llinputs, lloutput)
@@ -293,12 +293,12 @@
         # convert constants
         fgcc = FlowGraphConstantConverter(a.translator.graphs)
         fgcc.convert()
-        self.malloc_graph = a.bookkeeper.getdesc(self.gc.malloc.im_func).cachedgraph(None)
-        self.write_barrier_graph = a.bookkeeper.getdesc(self.gc.write_barrier.im_func).cachedgraph(None)
+        self.malloc_graph = a.bookkeeper.getdesc(self.gc.malloc.im_func).getuniquegraph()
+        self.write_barrier_graph = a.bookkeeper.getdesc(self.gc.write_barrier.im_func).getuniquegraph()
 
         # create a gc via invoking instantiate_gc
         self.gcptr = self.llinterp.eval_graph(
-            a.bookkeeper.getdesc(instantiate_gc).cachedgraph(None))
+            a.bookkeeper.getdesc(instantiate_gc).getuniquegraph())
         GETROOTS_FUNCTYPE = lltype.typeOf(
             getfunctionptr(a, dummy_get_roots1)).TO
         setattr(self.gcptr, "inst_get_roots",

Modified: pypy/dist/pypy/rpython/module/ll_stackless.py
==============================================================================
--- pypy/dist/pypy/rpython/module/ll_stackless.py	(original)
+++ pypy/dist/pypy/rpython/module/ll_stackless.py	Fri May 12 20:13:02 2006
@@ -18,3 +18,10 @@
     else:
         return to_opaque_object(newframetop)
 ll_stackless_switch.suggested_primitive = True
+
+
+def ll_stackless_clone(opaqueframetop):
+    frametop = from_opaque_object(opaqueframetop)
+    newframetop = frametop.clone()
+    return to_opaque_object(newframetop)
+ll_stackless_clone.suggested_primitive = True

Modified: pypy/dist/pypy/rpython/rstack.py
==============================================================================
--- pypy/dist/pypy/rpython/rstack.py	(original)
+++ pypy/dist/pypy/rpython/rstack.py	Fri May 12 20:13:02 2006
@@ -29,3 +29,5 @@
 class frame_stack_top(object):
     def switch(self):
         raise NotImplementedError("only works in translated versions")
+    def clone(self):
+        raise NotImplementedError("only works in translated versions")

Modified: pypy/dist/pypy/translator/c/database.py
==============================================================================
--- pypy/dist/pypy/translator/c/database.py	(original)
+++ pypy/dist/pypy/translator/c/database.py	Fri May 12 20:13:02 2006
@@ -223,10 +223,13 @@
                     show_i += 1000
             work_to_do = False
             if not is_later_yet:
-                newgcdependencies = self.gctransformer.finish()
-                if newgcdependencies:
+                newdependencies = self.gctransformer.finish() or []
+                if self.stacklesstransformer:
+                    newdependencies2 = self.stacklesstransformer.finish() or []
+                    newdependencies.extend(newdependencies2)
+                if newdependencies:
                     work_to_do = True
-                    for value in newgcdependencies:
+                    for value in newdependencies:
                         if isinstance(typeOf(value), ContainerType):
                             self.getcontainernode(value)
                         else:

Modified: pypy/dist/pypy/translator/c/genc.py
==============================================================================
--- pypy/dist/pypy/translator/c/genc.py	(original)
+++ pypy/dist/pypy/translator/c/genc.py	Fri May 12 20:13:02 2006
@@ -182,7 +182,7 @@
         # XXX check that the entrypoint has the correct
         # signature:  list-of-strings -> int
         bk = self.translator.annotator.bookkeeper
-        return getfunctionptr(bk.getdesc(self.entrypoint).cachedgraph(None))
+        return getfunctionptr(bk.getdesc(self.entrypoint).getuniquegraph())
 
     def getccompiler(self, extra_includes):
         # XXX for now, we always include Python.h

Modified: pypy/dist/pypy/translator/c/pyobj.py
==============================================================================
--- pypy/dist/pypy/translator/c/pyobj.py	(original)
+++ pypy/dist/pypy/translator/c/pyobj.py	Fri May 12 20:13:02 2006
@@ -573,7 +573,7 @@
                         # this is the context where we create the instance.
                         ann = self.translator.annotator
                         clsdef = ann.bookkeeper.getuniqueclassdef(cls)
-                        graph = ann.bookkeeper.getdesc(func).cachedgraph(None)
+                        graph = ann.bookkeeper.getdesc(func).getuniquegraph()
                         if ann.binding(graph.getargs()[0]).classdef is not clsdef:
                             value = new_method_graph(graph, clsdef, fname, self.translator)
                     self.name_for_meth[value] = fname

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	Fri May 12 20:13:02 2006
@@ -176,7 +176,7 @@
     t.buildannotator().build_types(func, [int])
     t.buildrtyper().specialize()
     bk = t.annotator.bookkeeper
-    graph = bk.getdesc(func).cachedgraph(None)
+    graph = bk.getdesc(func).getuniquegraph()
     return t, graph
 
 def test_function_call():

Modified: pypy/dist/pypy/translator/c/wrapper.py
==============================================================================
--- pypy/dist/pypy/translator/c/wrapper.py	(original)
+++ pypy/dist/pypy/translator/c/wrapper.py	Fri May 12 20:13:02 2006
@@ -40,7 +40,7 @@
             do_inline = True
         else:
             bk = translator.annotator.bookkeeper
-            graph = bk.getdesc(func).cachedgraph(None)
+            graph = bk.getdesc(func).getuniquegraph()
 
     f = getfunctionptr(graph)
     FUNCTYPE = typeOf(f).TO

Modified: pypy/dist/pypy/translator/driver.py
==============================================================================
--- pypy/dist/pypy/translator/driver.py	(original)
+++ pypy/dist/pypy/translator/driver.py	Fri May 12 20:13:02 2006
@@ -318,7 +318,7 @@
         translator = self.translator
         interp = LLInterpreter(translator.rtyper)
         bk = translator.annotator.bookkeeper
-        graph = bk.getdesc(self.entry_point).cachedgraph(None)
+        graph = bk.getdesc(self.entry_point).getuniquegraph()
         v = interp.eval_graph(graph,
                               self.extra.get('get_llinterp_args',
                                              lambda: [])())

Modified: pypy/dist/pypy/translator/js/js.py
==============================================================================
--- pypy/dist/pypy/translator/js/js.py	(original)
+++ pypy/dist/pypy/translator/js/js.py	Fri May 12 20:13:02 2006
@@ -39,7 +39,7 @@
         self.graph = []
         for  func in self.functions:
             bk   = self.db.translator.annotator.bookkeeper
-            ptr  = getfunctionptr(bk.getdesc(func).cachedgraph(None))
+            ptr  = getfunctionptr(bk.getdesc(func).getuniquegraph())
             c    = inputconst(lltype.typeOf(ptr), ptr)
             self.db.prepare_arg(c)
             self.graph.append( self.db.obj2node[c.value._obj].graph )

Modified: pypy/dist/pypy/translator/llvm/genllvm.py
==============================================================================
--- pypy/dist/pypy/translator/llvm/genllvm.py	(original)
+++ pypy/dist/pypy/translator/llvm/genllvm.py	Fri May 12 20:13:02 2006
@@ -179,7 +179,7 @@
         self.entrypoint = func
 
         bk = self.translator.annotator.bookkeeper
-        ptr = getfunctionptr(bk.getdesc(func).cachedgraph(None))
+        ptr = getfunctionptr(bk.getdesc(func).getuniquegraph())
         c = inputconst(lltype.typeOf(ptr), ptr)
         self.db.prepare_arg_value(c)
         self.entry_func_name = func.func_name

Modified: pypy/dist/pypy/translator/pyrex/genpyrex.py
==============================================================================
--- pypy/dist/pypy/translator/pyrex/genpyrex.py	(original)
+++ pypy/dist/pypy/translator/pyrex/genpyrex.py	Fri May 12 20:13:02 2006
@@ -451,7 +451,7 @@
                 list_methods=delay_methods.get(cls,[])
                 for methdesc in list_methods:
                     # XXX!
-                    graph = methdesc.funcdesc.cachedgraph(None)
+                    graph = methdesc.funcdesc.getuniquegraph()
                     hackedargs = ', '.join([var.name for var in graph.getargs()])
                     name = graph.name.split('.')[-1]
                     self.putline("def %s(%s):" % (name, hackedargs))

Modified: pypy/dist/pypy/translator/stackless/code.py
==============================================================================
--- pypy/dist/pypy/translator/stackless/code.py	(original)
+++ pypy/dist/pypy/translator/stackless/code.py	Fri May 12 20:13:02 2006
@@ -1,51 +1,33 @@
 from pypy.rpython.lltypesystem import lltype, llmemory, lloperation
 from pypy.rpython import rarithmetic
 from pypy.rpython import extfunctable
-
-SAVED_REFERENCE = lltype.Ptr(lltype.GcOpaqueType('stackless.saved_ref'))
-null_saved_ref = lltype.nullptr(SAVED_REFERENCE.TO)
-
-STORAGE_TYPES = [lltype.Void, SAVED_REFERENCE, llmemory.Address,
-                 lltype.Signed, lltype.Float, lltype.SignedLongLong]
-
-STORAGE_FIELDS = {SAVED_REFERENCE: 'ref',
-                  llmemory.Address: 'addr',
-                  lltype.Signed: 'long',
-                  lltype.Float: 'float',
-                  lltype.SignedLongLong: 'longlong',
-                  }
-
-RETVAL_VOID = 0
-for _key, _value in STORAGE_FIELDS.items():
-    globals()['RETVAL_' + _value.upper()] = STORAGE_TYPES.index(_key)
+from pypy.translator.stackless import frame
+from pypy.translator.stackless.frame import STATE_HEADER, SAVED_REFERENCE
 
 # ____________________________________________________________
 
+SWITCH_STATE = frame.make_state_header_type('switch_state',
+                                            ('c', SAVED_REFERENCE))
+
 def ll_frame_switch(targetstate):
-    if global_state.restart_substate == 0:
+    if global_state.restart_substate == -1:
         # normal entry point for a call to state.switch()
         # first unwind the stack
         u = UnwindException()
         s = lltype.malloc(SWITCH_STATE)
-        s.header.restartstate = 1
-        # the next three lines are pure rtyper-pleasing hacks
-        f = ll_frame_switch
-        if global_state.restart_substate:
-            f = None
+        s.header.f_restart = INDEX_SWITCH
         s.c = lltype.cast_opaque_ptr(SAVED_REFERENCE, targetstate)
-        s.header.function = llmemory.cast_ptr_to_adr(f)
-        s.header.retval_type = RETVAL_REF
         add_frame_state(u, s.header)
         raise u
-    elif global_state.restart_substate == 1:
-        # STATE 1: we didn't do anything so far, but the stack is unwound
-        global_state.restart_substate = 0
+    elif global_state.restart_substate == 0:
+        # STATE 0: we didn't do anything so far, but the stack is unwound
+        global_state.restart_substate = -1
         # grab the frame corresponding to ourself, and prepare it for
-        # the future switch() back, which will go to STATE 2 below
+        # the future switch() back, which will go to STATE 1 below
         sourcestate = global_state.top
-        sourcestate.restartstate = 2
+        sourcestate.f_restart = INDEX_SWITCH + 1
         # the 'targetstate' local is garbage here, it must be read back from
-        # 's.c' where we saved it by STATE 0 above
+        # 's.c' where we saved it by the normal entry point above
         s = lltype.cast_pointer(lltype.Ptr(SWITCH_STATE), sourcestate)
         targetstate = lltype.cast_opaque_ptr(lltype.Ptr(STATE_HEADER), s.c)
         global_state.top = targetstate
@@ -53,118 +35,86 @@
                                                          sourcestate)
         raise UnwindException()   # this jumps to targetstate
     else:
-        # STATE 2: switching back into a tasklet suspended by
+        # STATE 1: switching back into a tasklet suspended by
         # a call to switch()
-        global_state.top = null_state
-        global_state.restart_substate = 0
-        origin_state = lltype.cast_opaque_ptr(OPAQUE_STATE_HEADER_PTR,
+        global_state.top = frame.null_state
+        global_state.restart_substate = -1
+        origin_state = lltype.cast_opaque_ptr(frame.OPAQUE_STATE_HEADER_PTR,
                                               fetch_retval_ref())
         return origin_state    # a normal return into the current tasklet,
                                # with the source state as return value
 ll_frame_switch.stackless_explicit = True
 
-STATE_HEADER = lltype.GcStruct('state_header',
-                               ('f_back',       lltype.Ptr(lltype.GcForwardReference())),
-                               ('restartstate', lltype.Signed),
-                               ('function',     llmemory.Address),
-                               ('retval_type',  lltype.Signed),
-                               adtmeths={'switch': ll_frame_switch})
-STATE_HEADER.f_back.TO.become(STATE_HEADER)
-
-null_state = lltype.nullptr(STATE_HEADER)
-
-OPAQUE_STATE_HEADER_PTR = lltype.Ptr(
-    extfunctable.frametop_type_info.get_lltype())
-
-##def decode_state(currentframe): 
-##    return (currentframe.function,
-##            currentframe.retval_type,
-##            currentframe.restartstate)
-##decode_state.stackless_explicit = True
-
-SWITCH_STATE = lltype.GcStruct('state_switch',
-                               ('header', STATE_HEADER),
-                               ('c', SAVED_REFERENCE))
+INDEX_SWITCH = frame.RestartInfo.add_prebuilt(ll_frame_switch, 2)
+
+# ____________________________________________________________
 
 def yield_current_frame_to_caller():
-    if global_state.restart_substate == 0:
+    if global_state.restart_substate == -1:
         # normal entry point for yield_current_frame_to_caller()
         # first unwind the stack
         u = UnwindException()
         s = lltype.malloc(STATE_HEADER)
-        s.restartstate = 1
-        # the next three lines are pure rtyper-pleasing hacks
-        f = yield_current_frame_to_caller
-        if global_state.restart_substate:
-            f = None
-        s.function = llmemory.cast_ptr_to_adr(f)
-        s.retval_type = RETVAL_REF
+        s.f_restart = INDEX_YCFTC
         add_frame_state(u, s)
-        raise u   # this goes to 'STATE 1' below
+        raise u   # this goes to 'STATE 0' below
 
-    elif global_state.restart_substate == 1:
-        # STATE 1: we didn't do anything so far, but the stack is unwound
-        global_state.restart_substate = 0
+    elif global_state.restart_substate == 0:
+        # STATE 0: we didn't do anything so far, but the stack is unwound
+        global_state.restart_substate = -1
         ycftc_state = global_state.top
         our_caller_state = ycftc_state.f_back
         caller_state = our_caller_state.f_back
-        # the next three lines are pure rtyper-pleasing hacks
-        f = yield_current_frame_to_caller
-        if global_state.restart_substate:
-            f = None
         # when our immediate caller finishes (which is later, when the
-        # tasklet finishes), then we will jump to 'STATE 2' below
+        # tasklet finishes), then we will jump to 'STATE 1' below
         endstate = lltype.malloc(STATE_HEADER)
-        endstate.restartstate = 2
-        endstate.function = llmemory.cast_ptr_to_adr(f)
+        endstate.f_restart = INDEX_YCFTC + 1
         our_caller_state.f_back = endstate
         global_state.top = caller_state
         global_state.retval_ref = lltype.cast_opaque_ptr(SAVED_REFERENCE,
                                                          our_caller_state)
         raise UnwindException()  # this goes to the caller's caller
 
-    elif global_state.restart_substate == 2:
-        # STATE 2: this is a slight abuse of yield_current_frame_to_caller(),
+    elif global_state.restart_substate == 1:
+        # STATE 1: this is a slight abuse of yield_current_frame_to_caller(),
         # as we return here when our immediate caller returns (and thus the
         # new tasklet finishes).
-        global_state.restart_substate = 0
+        global_state.restart_substate = -1
         next_state = lltype.cast_opaque_ptr(lltype.Ptr(STATE_HEADER),
                                             fetch_retval_ref())
         # return a NULL state pointer to the target of the implicit switch
         global_state.top = next_state
-        global_state.retval_ref = null_saved_ref
+        global_state.retval_ref = frame.null_saved_ref
         raise UnwindException()  # this goes to the switch target given by
                                  # the 'return' at the end of our caller
 
     else:
-        # STATE 3: this is never reached!  But the annotator doesn't know it,
+        # this is never reached!  But the annotator doesn't know it,
         # so it makes the whole function be annotated as returning a random
         # non-constant STATE_HEADER pointer.
-        return lltype.cast_opaque_ptr(OPAQUE_STATE_HEADER_PTR,
+        return lltype.cast_opaque_ptr(frame.OPAQUE_STATE_HEADER_PTR,
                                       global_state.top)
 
 yield_current_frame_to_caller.stackless_explicit = True
 
+INDEX_YCFTC = frame.RestartInfo.add_prebuilt(yield_current_frame_to_caller, 2)
+
+# ____________________________________________________________
+
 def stack_frames_depth():
-    if not global_state.restart_substate:
+    if global_state.restart_substate == -1:
         # normal entry point for stack_frames_depth()
         # first unwind the stack
         u = UnwindException()
         s = lltype.malloc(STATE_HEADER)
-        s.restartstate = 1
-        # the next three lines are pure rtyper-pleasing hacks
-        f = stack_frames_depth
-        if global_state.restart_substate:
-            f = None
-        s.function = llmemory.cast_ptr_to_adr(f)
-        s.retval_type = RETVAL_LONG
+        s.f_restart = INDEX_DEPTH
         add_frame_state(u, s)
-        raise u    # goes to STATE 1 below
+        raise u    # goes to STATE 0 below
     else:
-        # STATE 1: now the stack is unwound, and we can count the frames
+        # STATE 0: now the stack is unwound, and we can count the frames
         # in the heap
         cur = global_state.top
-        global_state.restart_substate = 0
+        global_state.restart_substate = -1
         depth = 0
         while cur:
             depth += 1
@@ -172,56 +122,60 @@
         return depth
 stack_frames_depth.stackless_explicit = True
 
+INDEX_DEPTH = frame.RestartInfo.add_prebuilt(stack_frames_depth, 1)
+
+# ____________________________________________________________
+
 def ll_stack_unwind():
-    if not global_state.restart_substate:
+    if global_state.restart_substate == -1:
         # normal entry point for stack_frames_depth()
         # first unwind the stack in the usual way
         u = UnwindException()
         s = lltype.malloc(STATE_HEADER)
-        s.restartstate = 1
-        # the next three lines are pure rtyper-pleasing hacks
-        f = ll_stack_unwind
-        if global_state.restart_substate:
-            f = None
-        s.function = llmemory.cast_ptr_to_adr(f)
-        s.retval_type = RETVAL_VOID
+        s.f_restart = INDEX_UNWIND
         add_frame_state(u, s)
-        raise u    # goes to STATE 1 below
+        raise u    # goes to STATE 0 below
     else:
-        # STATE 1: now the stack is unwound.  That was the goal.
+        # STATE 0: now the stack is unwound.  That was the goal.
         # Return to caller.
-        global_state.restart_substate = 0
+        global_state.restart_substate = -1
 ll_stack_unwind.stackless_explicit = True
 
+INDEX_UNWIND = frame.RestartInfo.add_prebuilt(ll_stack_unwind, 1)
+
+# ____________________________________________________________
+
 class StacklessData:
     def __init__(self):
-        self.top = null_state
-        self.restart_substate = 0
+        self.top = frame.null_state
+        self.restart_substate = -1
         self.retval_long = 0
         self.retval_longlong = rarithmetic.r_longlong(0)
         self.retval_float = 0.0
         self.retval_addr = llmemory.NULL
-        self.retval_ref = null_saved_ref
+        self.retval_ref = frame.null_saved_ref
         self.exception = None
+        self.masterarray = lltype.malloc(frame.FRAME_INFO_ARRAY, 0,
+                                         immortal=True)
 
 global_state = StacklessData()
 
 def call_function(fn, retval_code):
-    if retval_code == RETVAL_VOID:
+    if retval_code == frame.RETVAL_VOID:
         lloperation.llop.unsafe_call(lltype.Void, fn)
-    elif retval_code == RETVAL_REF:
+    elif retval_code == frame.RETVAL_REF:
         global_state.retval_ref = lloperation.llop.unsafe_call(
             SAVED_REFERENCE, fn)
-    elif retval_code == RETVAL_ADDR:
+    elif retval_code == frame.RETVAL_ADDR:
         global_state.retval_addr = lloperation.llop.unsafe_call(
             llmemory.Address, fn)
-    elif retval_code == RETVAL_LONG:
+    elif retval_code == frame.RETVAL_LONG:
         global_state.retval_long = lloperation.llop.unsafe_call(
             lltype.Signed, fn)
-    elif retval_code == RETVAL_FLOAT:
+    elif retval_code == frame.RETVAL_FLOAT:
         global_state.retval_float = lloperation.llop.unsafe_call(
             lltype.Float, fn)
-    elif retval_code == RETVAL_LONGLONG:
+    elif retval_code == frame.RETVAL_LONGLONG:
         global_state.retval_longlong = lloperation.llop.unsafe_call(
             lltype.SignedLongLong, fn)
 call_function.stackless_explicit = True
@@ -235,7 +189,8 @@
         # To switch manually to a different frame, code issues a regular
         # UnwindException first, to empty the C stack, and then issues a
         # (XXX complete this comment)
-        self.frame_bottom = null_state
+        self.frame_bottom = frame.null_state
+    __init__.stackless_explicit = True
 
 def slp_main_loop():
     """
@@ -244,12 +199,12 @@
     pending = global_state.top
     
     while True:
-        back                          = pending.f_back
-        fn                            = pending.function
-        signature                     = pending.retval_type
-        global_state.restart_substate = pending.restartstate
+        back = pending.f_back
+        decoded = frame.decodestate(global_state.masterarray,
+                                    pending.f_restart)
+        (fn, global_state.restart_substate, retval_type) = decoded
         try:
-            call_function(fn, signature)
+            call_function(fn, retval_type)
         except UnwindException, u:   #XXX annotation support needed
             if u.frame_bottom:
                 u.frame_bottom.f_back = back
@@ -274,22 +229,6 @@
         u.frame_bottom = frame_state
 add_frame_state.stackless_explicit = True
 
-def resume_state():
-    """Return and zero the 'restart_substate', the index of the resume
-    point to jump to or zero for the not resuming case."""
-    x = global_state.restart_substate
-    global_state.restart_substate = 0
-    return x 
-resume_state.stackless_explicit = True
-
-# XXX would like to be able to say
-#def resume_header():
-#    x = global_state.restart_substate
-#    if x:
-#        top = global_state.top
-#        global_state.top = None
-# XXX and then insert the rtyped graph of this into functions
-        
 def fetch_retval_void():
     e = global_state.exception
     if e:
@@ -342,6 +281,6 @@
         raise e
     else:
         res = global_state.retval_ref
-        global_state.retval_ref = null_saved_ref
+        global_state.retval_ref = frame.null_saved_ref
         return res
 fetch_retval_ref.stackless_explicit = True

Added: pypy/dist/pypy/translator/stackless/frame.py
==============================================================================
--- (empty file)
+++ pypy/dist/pypy/translator/stackless/frame.py	Fri May 12 20:13:02 2006
@@ -0,0 +1,144 @@
+from pypy.rpython.lltypesystem import lltype, llmemory
+from pypy.rpython import extfunctable
+from pypy.rpython.typesystem import getfunctionptr
+from pypy.objspace.flow.model import FunctionGraph
+
+# ____________________________________________________________
+# generic data types
+
+SAVED_REFERENCE = lltype.Ptr(lltype.GcOpaqueType('stackless.saved_ref'))
+null_saved_ref = lltype.nullptr(SAVED_REFERENCE.TO)
+
+STORAGE_TYPES = [lltype.Void, SAVED_REFERENCE, llmemory.Address,
+                 lltype.Signed, lltype.Float, lltype.SignedLongLong]
+
+STORAGE_FIELDS = {SAVED_REFERENCE: 'ref',
+                  llmemory.Address: 'addr',
+                  lltype.Signed: 'long',
+                  lltype.Float: 'float',
+                  lltype.SignedLongLong: 'longlong',
+                  }
+
+RETVAL_VOID = 0
+for _key, _value in STORAGE_FIELDS.items():
+    globals()['RETVAL_' + _value.upper()] = STORAGE_TYPES.index(_key)
+
+def storage_type(T):
+    """Return the 'erased' storage type corresponding to T.
+    """
+    if T is lltype.Void:
+        return lltype.Void
+    elif isinstance(T, lltype.Ptr):
+        if T._needsgc():
+            return SAVED_REFERENCE
+        else:
+            return llmemory.Address
+    elif T is lltype.Float:
+        return lltype.Float
+    elif T in [lltype.SignedLongLong, lltype.UnsignedLongLong]:
+        return lltype.SignedLongLong
+    elif T is llmemory.Address:
+        return llmemory.Address
+    elif isinstance(T, lltype.Primitive):
+        return lltype.Signed
+    else:
+        raise Exception("don't know about %r" % (T,))
+
+# ____________________________________________________________
+# structures for saved frame states
+
+STATE_HEADER = lltype.GcStruct('state_header',
+                           ('f_back', lltype.Ptr(lltype.GcForwardReference())),
+                           ('f_restart', lltype.Signed))
+STATE_HEADER.f_back.TO.become(STATE_HEADER)
+
+null_state = lltype.nullptr(STATE_HEADER)
+
+OPAQUE_STATE_HEADER_PTR = lltype.Ptr(
+    extfunctable.frametop_type_info.get_lltype())
+
+
+def make_state_header_type(name, *fields):
+##    source = ['def ll_reccopy_%s(frame):' % name,
+##              '    if frame.f_back:'
+##              '        prev = frame.f_back.XXX',
+##              '    newframe = lltype.malloc(lltype.typeOf(FRAME))',
+##              '    newframe.']
+    
+##    copynames = [name for (name, _) in fields]
+##    copynames.append('header.restartstate')
+##    copynames.append('header.function')
+##    copynames.append('header.retval_type')
+##    for name in copynames:
+##        source.append('    newframe.%s = frame.%s' % (name, name))
+##    source.append('    return newframe')
+##    source.append('')
+##    miniglobals = {'lltype': lltype}
+##    exec compile2('\n'.join(source)) in miniglobals
+##    extras = {
+##        'adtmeths': {'reccopy': miniglobals['ll_frame_reccopy']}
+##        }
+    return lltype.GcStruct(name,
+                           ('header', STATE_HEADER),
+                           *fields)
+
+# ____________________________________________________________
+# master array giving information about the restart points
+# (STATE_HEADER.frameinfo is an index into this array)
+
+FRAME_INFO = lltype.Struct('frame_info',
+                           ('fnaddr', llmemory.Address),
+                           ('info',   lltype.Signed))
+FRAME_INFO_ARRAY = lltype.Array(FRAME_INFO)
+
+def decodestate(masterarray, index):
+    finfo = masterarray[index]
+    if finfo.fnaddr:
+        restartstate = 0
+    else:
+        restartstate = finfo.info
+        finfo = masterarray[index - restartstate]
+    return (finfo.fnaddr,  # function ptr
+            restartstate,  # restart state within function
+            finfo.info)    # retval_type
+decodestate.stackless_explicit = True
+
+
+class RestartInfo(object):
+    __slots__ = ['func_or_graph',
+                 'first_index',
+                 'nb_restart_states']
+
+    def __init__(self, func_or_graph, first_index, nb_restart_states):
+        self.func_or_graph = func_or_graph
+        self.first_index = first_index
+        self.nb_restart_states = nb_restart_states
+
+    def compress(self, rtyper, masterarray):
+        if self.nb_restart_states > 0:
+            graph = self.func_or_graph
+            if not isinstance(graph, FunctionGraph):
+                bk = rtyper.annotator.bookkeeper
+                graph = bk.getdesc(graph).getuniquegraph()
+            funcptr = getfunctionptr(graph)
+            rettype = lltype.typeOf(funcptr).TO.RESULT
+            retval_type = STORAGE_TYPES.index(storage_type(rettype))
+
+            finfo = masterarray[self.first_index]
+            finfo.fnaddr = llmemory.cast_ptr_to_adr(funcptr)
+            finfo.info = retval_type
+            for i in range(1, self.nb_restart_states):
+                finfo = masterarray[self.first_index+i]
+                finfo.info = i
+
+    prebuilt = []
+    prebuiltindex = 0
+
+    def add_prebuilt(cls, func, nb_restart_states):
+        assert func.stackless_explicit    # did you forget this flag?
+        n = cls.prebuiltindex
+        restart = cls(func, n, nb_restart_states)
+        cls.prebuilt.append(restart)
+        cls.prebuiltindex += restart.nb_restart_states
+        return n
+    add_prebuilt = classmethod(add_prebuilt)

Modified: pypy/dist/pypy/translator/stackless/transform.py
==============================================================================
--- pypy/dist/pypy/translator/stackless/transform.py	(original)
+++ pypy/dist/pypy/translator/stackless/transform.py	Fri May 12 20:13:02 2006
@@ -6,37 +6,17 @@
 from pypy.translator import unsimplify
 from pypy.annotation import model as annmodel
 from pypy.rpython.annlowlevel import MixLevelHelperAnnotator
-from pypy.translator.stackless import code
-from pypy.translator.stackless.code import SAVED_REFERENCE, STORAGE_TYPES
-from pypy.translator.stackless.code import STORAGE_FIELDS
+from pypy.translator.stackless import code, frame
 from pypy.rpython.rclass import getinstancerepr
 from pypy.rpython.rbuiltin import gen_cast
 from pypy.rpython.rtyper import LowLevelOpList
 from pypy.rpython.module import ll_stackless, ll_stack
 from pypy.translator.backendopt import graphanalyze
 
-from pypy.translator.stackless.code import STATE_HEADER, null_state
-
-def storage_type(T):
-    """Return the 'erased' storage type corresponding to T.
-    """
-    if T is lltype.Void:
-        return lltype.Void
-    elif isinstance(T, lltype.Ptr):
-        if T._needsgc():
-            return SAVED_REFERENCE
-        else:
-            return llmemory.Address
-    elif T is lltype.Float:
-        return lltype.Float
-    elif T in [lltype.SignedLongLong, lltype.UnsignedLongLong]:
-        return lltype.SignedLongLong
-    elif T is llmemory.Address:
-        return llmemory.Address
-    elif isinstance(T, lltype.Primitive):
-        return lltype.Signed
-    else:
-        raise Exception("don't know about %r" % (T,))
+from pypy.translator.stackless.frame import SAVED_REFERENCE, STORAGE_TYPES
+from pypy.translator.stackless.frame import STORAGE_FIELDS
+from pypy.translator.stackless.frame import STATE_HEADER, null_state
+from pypy.translator.stackless.frame import storage_type
 
 # a simple example of what the stackless transform does
 #
@@ -44,29 +24,31 @@
 #     return g() + x + 1
 #
 # STATE_func_0 = lltype.Struct('STATE_func_0',
-#                              ('header', code.STATE_HEADER),
+#                              ('header', STATE_HEADER),
 #                              ('saved_long_0', Signed))
 #
 # def func(x):
 #     state = global_state.restart_substate
-#     global_state.restart_substate = 0
-#     if state == 0:   # normal case
+#     if state == -1:   # normal case
 #         try:
 #             retval = g(x)
 #         except code.UnwindException, u:
 #             state = lltype.malloc(STATE_func_0)
-#             state.header.restartstate = 1
-#             state.header.function = llmemory.cast_ptr_to_adr(func)
-#             state.header.retval_type = code.RETVAL_LONG
+#             state.header.f_restart = 
 #             state.saved_long_0 = x
 #             code.add_frame_state(u, state.header)
 #             raise
-#     elif state == 1:
+#     elif state == 0:
+#         global_state.restart_substate = -1
 #         state = lltype.cast_pointer(lltype.Ptr(STATE_func_0),
 #                                     global_state.top)
 #         global_state.top = null_state
 #         x = state.saved_long_0
 #         retval = code.fetch_retval_long() # can raise an exception
+#     elif state == 1:
+#         ...
+#     elif state == 2:
+#         ...
 #     else:
 #         abort()
 #     return retval + x + 1
@@ -104,9 +86,7 @@
             for t in STORAGE_TYPES:
                 for j in range(counts.get(t, 0)):
                     fields.append(('state_%s_%d' % (STORAGE_FIELDS[t], j), t))
-            T = lltype.GcStruct("FrameState",
-                                ('header', STATE_HEADER),
-                                *fields)
+            T = frame.make_state_header_type("FrameState", *fields)
             self.frametypes[key] = T
         return T, fieldnames
 
@@ -140,6 +120,8 @@
         self.translator = translator
 
         self.frametyper = FrameTyper()
+        self.restartinfos = frame.RestartInfo.prebuilt[:]
+        self.restartinfoindex = frame.RestartInfo.prebuiltindex
         self.curr_graph = None
         
         bk = translator.annotator.bookkeeper
@@ -150,6 +132,13 @@
         self.analyzer = StacklessAnalyzer(translator,
                                           self.unwind_exception_type)
 
+        # the point of this little dance is to not annotate
+        # code.global_state.masterarray as a constant.
+        data_classdef = bk.getuniqueclassdef(code.StacklessData)
+        data_classdef.generalize_attr(
+            'masterarray',
+            annmodel.SomePtr(lltype.Ptr(frame.FRAME_INFO_ARRAY)))
+
         mixlevelannotator = MixLevelHelperAnnotator(translator.rtyper)
         l2a = annmodel.lltype_to_annotation
 
@@ -163,7 +152,7 @@
         slp_entry_point.stackless_explicit = True
 
         self.slp_entry_point = slp_entry_point
-        oldgraph = bk.getdesc(entrypoint).cachedgraph(None)
+        oldgraph = bk.getdesc(entrypoint).getuniquegraph()
         s_argv = translator.annotator.binding(oldgraph.getargs()[0])
         self.slp_entry_point_ptr = mixlevelannotator.constfunc(
             slp_entry_point, [s_argv], annmodel.SomeInteger())
@@ -175,9 +164,6 @@
              annmodel.SomePtr(lltype.Ptr(STATE_HEADER))],
             l2a(lltype.Void))
 
-        self.resume_state_ptr = mixlevelannotator.constfunc(
-            code.resume_state, [], annmodel.SomeInteger())
-
         self.fetch_retvals = {
             lltype.Void: mixlevelannotator.constfunc(
                 code.fetch_retval_void, [], annmodel.s_None),
@@ -193,7 +179,7 @@
                 code.fetch_retval_ref, [], annmodel.SomePtr(SAVED_REFERENCE)),
             }
 
-        s_StatePtr = annmodel.SomePtr(code.OPAQUE_STATE_HEADER_PTR)
+        s_StatePtr = annmodel.SomePtr(frame.OPAQUE_STATE_HEADER_PTR)
         self.suggested_primitives = {
             ll_stackless.ll_stackless_stack_frames_depth:
                 mixlevelannotator.constfunc(
@@ -217,9 +203,19 @@
             r_global_state.lowleveltype)
         self.seen_blocks = set()
 
+        # some prebuilt constants to save memory
+        self.c_restart_substate_name = model.Constant("inst_restart_substate",
+                                                      lltype.Void)
+        self.c_inst_top_name = model.Constant("inst_top", lltype.Void)
+        self.c_f_restart_name = model.Constant("f_restart", lltype.Void)
+        self.c_minus_one = model.Constant(-1, lltype.Signed)
+        self.c_null_state = model.Constant(null_state,
+                                           lltype.typeOf(null_state))
+
     def transform_all(self):
         for graph in self.translator.graphs:
             self.transform_graph(graph)
+        self.finish()
         
     def transform_graph(self, graph):
         self.resume_points = []
@@ -241,6 +237,7 @@
 
         if self.resume_points:
             self.insert_resume_handling(graph)
+            self.generate_restart_infos(graph)
 
         model.checkgraph(graph)
 
@@ -274,23 +271,28 @@
         new_start_block = model.Block(newinputargs)
         var_resume_state = varoftype(lltype.Signed)
         new_start_block.operations.append(
-            model.SpaceOperation("direct_call",
-                                 [self.resume_state_ptr],
+            model.SpaceOperation("getfield",
+                                 [self.ll_global_state,
+                                  self.c_restart_substate_name],
                                  var_resume_state))
-        not_resuming_link = model.Link(newinputargs, old_start_block, 0)
-        not_resuming_link.llexitcase = 0
+        not_resuming_link = model.Link(newinputargs, old_start_block, -1)
+        not_resuming_link.llexitcase = -1
         resuming_links = []
         for resume_point_index, resume_point in enumerate(self.resume_points):
             newblock = model.Block([])
             newargs = []
             llops = LowLevelOpList()
+            llops.genop("setfield",
+                        [self.ll_global_state,
+                         self.c_restart_substate_name,
+                         self.c_minus_one])
             frame_state_type = resume_point.frame_state_type
             frame_top = varoftype(lltype.Ptr(frame_state_type))
             llops.extend(self.ops_read_global_state_field(frame_top, "top"))
             llops.genop("setfield",
                        [self.ll_global_state,
-                        model.Constant("inst_top", lltype.Void),
-                        model.Constant(null_state, lltype.typeOf(null_state))])
+                        self.c_inst_top_name,
+                        self.c_null_state])
             varmap = {}
             for i, arg in enumerate(resume_point.args):
                 assert arg is not resume_point.var_result
@@ -351,8 +353,8 @@
                 # end ouch!
             
             resuming_links.append(
-                model.Link([], newblock, resume_point_index+1))
-            resuming_links[-1].llexitcase = resume_point_index+1
+                model.Link([], newblock, resume_point_index))
+            resuming_links[-1].llexitcase = resume_point_index
         new_start_block.exitswitch = var_resume_state
         new_start_block.closeblock(not_resuming_link, *resuming_links)
 
@@ -499,24 +501,11 @@
             [self.add_frame_state_ptr, var_exc, var_header],
             varoftype(lltype.Void)))
 
+        f_restart = self.restartinfoindex + len(self.resume_points)
         saveops.append(model.SpaceOperation(
             "setfield",
-            [var_header, model.Constant("restartstate", lltype.Void), 
-             model.Constant(len(self.resume_points)+1, lltype.Signed)],
-            varoftype(lltype.Void)))
-
-        funcptr = rtyper.type_system.getcallable(self.curr_graph)
-        saveops.append(model.SpaceOperation(
-            "setfield",
-            [var_header, model.Constant("function", lltype.Void), 
-             model.Constant(llmemory.fakeaddress(funcptr), llmemory.Address)],
-            varoftype(lltype.Void)))
-        rettype = lltype.typeOf(funcptr).TO.RESULT
-        retval_type = STORAGE_TYPES.index(storage_type(rettype))
-
-        saveops.append(model.SpaceOperation(
-            "setfield", [var_header, model.Constant("retval_type", lltype.Void), 
-                         model.Constant(retval_type, lltype.Signed)],
+            [var_header, self.c_f_restart_name,
+             model.Constant(f_restart, lltype.Signed)],
             varoftype(lltype.Void)))
 
         type_repr = rclass.get_type_repr(rtyper)
@@ -544,3 +533,23 @@
             v_typeerased = gen_cast(llops, t, var)
             llops.genop('setfield', [frame_state_var, fname, v_typeerased])
         return llops
+
+    def generate_restart_infos(self, graph):
+        restartinfo = frame.RestartInfo(graph, self.restartinfoindex,
+                                        len(self.resume_points))
+        self.restartinfos.append(restartinfo)
+        self.restartinfoindex += len(self.resume_points)
+
+    def finish(self):
+        # compute the final masterarray
+        masterarray = lltype.malloc(frame.FRAME_INFO_ARRAY,
+                                    self.restartinfoindex,
+                                    immortal=True)
+        rtyper = self.translator.rtyper
+        for restartinfo in self.restartinfos:
+            restartinfo.compress(rtyper, masterarray)
+        # horrors in the same spirit as in rpython.memory.gctransform
+        # (shorter, though)
+        ll_global_state = self.ll_global_state.value
+        ll_global_state.inst_masterarray = masterarray
+        return [masterarray]


From antocuni at codespeak.net  Fri May 12 20:40:11 2006
From: antocuni at codespeak.net (antocuni at codespeak.net)
Date: Fri, 12 May 2006 20:40:11 +0200 (CEST)
Subject: [pypy-svn] r27154 - in pypy/dist/pypy/rpython: ootypesystem test
Message-ID: <20060512184011.57C09100BC@code0.codespeak.net>

Author: antocuni
Date: Fri May 12 20:40:03 2006
New Revision: 27154

Modified:
   pypy/dist/pypy/rpython/ootypesystem/rstr.py
   pypy/dist/pypy/rpython/test/test_rstr.py
Log:
Added support for string iteration and some tests in ootypesystem.
 


Modified: pypy/dist/pypy/rpython/ootypesystem/rstr.py
==============================================================================
--- pypy/dist/pypy/rpython/ootypesystem/rstr.py	(original)
+++ pypy/dist/pypy/rpython/ootypesystem/rstr.py	Fri May 12 20:40:03 2006
@@ -3,7 +3,11 @@
      AbstractUniCharRepr, AbstractStringIteratorRepr,\
      AbstractLLHelpers
 from pypy.rpython.lltypesystem.lltype import Ptr, Char, UniChar
-from pypy.rpython.ootypesystem.ootype import Signed, Record, String, make_string
+from pypy.rpython.ootypesystem import ootype
+
+# TODO: investigate if it's possibile and it's worth to concatenate a
+# String and a Char directly without passing to Char-->String
+# conversion
 
 class StringRepr(AbstractStringRepr):
     """
@@ -23,7 +27,7 @@
     new low-level operation (convert_char_to_oostring or some such) for this.
     """
 
-    lowleveltype = String
+    lowleveltype = ootype.String
 
     def __init__(self, *args):
         AbstractStringRepr.__init__(self, *args)
@@ -31,10 +35,10 @@
 
     def convert_const(self, value):
         if value is None:
-            return String._null
+            return ootype.String._null
         if not isinstance(value, str):
             raise TyperError("not a str: %r" % (value,))
-        return make_string(value)
+        return ootype.make_string(value)
 
     def make_iterator_repr(self):
         return string_iterator_repr
@@ -47,7 +51,6 @@
     lowleveltype = UniChar
 
 class LLHelpers(AbstractLLHelpers):
-
     def ll_stritem_nonneg(s, i):
         return s.ll_stritem_nonneg(i)
 
@@ -57,6 +60,7 @@
     def ll_strconcat(s1, s2):
         return s1.ll_strconcat(s2)
 
+
 string_repr = StringRepr()
 char_repr = CharRepr()
 unichar_repr = UniCharRepr()
@@ -64,7 +68,26 @@
 unichar_repr.ll = LLHelpers
 
 class StringIteratorRepr(AbstractStringIteratorRepr):
+    lowleveltype = ootype.Record({'string': string_repr.lowleveltype,
+                                  'index': ootype.Signed})
+
+    def __init__(self):
+        self.ll_striter = ll_striter
+        self.ll_strnext = ll_strnext
+
+def ll_striter(string):
+    iter = ootype.new(string_iterator_repr.lowleveltype)
+    iter.string = string
+    iter.index = 0
+    return iter
+
+def ll_strnext(iter):
+    string = iter.string    
+    index = iter.index
+    if index >= string.ll_strlen():
+        raise StopIteration
+    iter.index = index + 1
+    return string.ll_stritem_nonneg(index)
 
-    lowleveltype = Record({'string': string_repr.lowleveltype, 'index': Signed})
+string_iterator_repr = StringIteratorRepr()
 
-string_iterator_repr = StringIteratorRepr

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 May 12 20:40:03 2006
@@ -84,42 +84,44 @@
                 res = self.interpret(fn, [i,j])
                 assert self.ll_to_string(res) == 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
-
-    for i in range(3):
-        res = interpret(fn, [i])
-        assert res is True
+    def test_iter(self):
+        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
+
+        for i in range(3):
+            res = self.interpret(fn, [i])
+            assert res is True
         
-def test_char_constant():
-    def fn(s):
-        return s + '.'
-    res = interpret(fn, ['x'])
-    assert len(res.chars) == 2
-    assert res.chars[0] == 'x'
-    assert res.chars[1] == '.'
-
-def test_char_isxxx():
-    def fn(s):
-        return (s.isspace()      |
-                s.isdigit() << 1 |
-                s.isalpha() << 2 |
-                s.isalnum() << 3 |
-                s.isupper() << 4 |
-                s.islower() << 5)
-    for i in range(128):
-        ch = chr(i)
-        res = interpret(fn, [ch])
-        assert res == fn(ch)
+    def test_char_constant(self):
+        self._skip_oo('conversion char-->string')
+        def fn(s):
+            return s + '.'
+        res = self.interpret(fn, ['x'])
+        res = self.ll_to_string(res)
+        assert len(res) == 2
+        assert res[0] == 'x'
+        assert res[1] == '.'
+
+    def test_char_isxxx(self):
+        def fn(s):
+            return (s.isspace()      |
+                    s.isdigit() << 1 |
+                    s.isalpha() << 2 |
+                    s.isalnum() << 3 |
+                    s.isupper() << 4 |
+                    s.islower() << 5)
+        for i in range(128):
+            ch = chr(i)
+            res = self.interpret(fn, [ch])
+            assert res == fn(ch)
 
 def test_char_compare():
     res = interpret(lambda c1, c2: c1 == c2,  ['a', 'b'])
@@ -565,7 +567,7 @@
     res = interpret(g, [-2])
     assert res._obj.value == 42
 
-class TestLltype(AbstractTestRstr):
+class xTestLltype(AbstractTestRstr):
     ts = "lltype"
 
     def ll_to_string(self, s):


From arigo at codespeak.net  Fri May 12 23:50:12 2006
From: arigo at codespeak.net (arigo at codespeak.net)
Date: Fri, 12 May 2006 23:50:12 +0200 (CEST)
Subject: [pypy-svn] r27157 - in pypy/dist/pypy: annotation rpython
	translator translator/stackless translator/stackless/test
Message-ID: <20060512215012.80D8E100AA@code0.codespeak.net>

Author: arigo
Date: Fri May 12 23:50:10 2006
New Revision: 27157

Added:
   pypy/dist/pypy/translator/stackless/test/test_clone.py   (contents, props changed)
Modified:
   pypy/dist/pypy/annotation/annrpython.py
   pypy/dist/pypy/rpython/rtyper.py
   pypy/dist/pypy/translator/stackless/code.py
   pypy/dist/pypy/translator/stackless/frame.py
   pypy/dist/pypy/translator/stackless/transform.py
   pypy/dist/pypy/translator/unsimplify.py
Log:
(pedronis, arigo)
The first, naive and simple test_clone.  As expected, the hard part is to
get it right with respect to the annotator and the rtyper and mixlevelhelpers.
This means a bug fix in copyvar() (!) and Yet Another Dict on the annotator.


Modified: pypy/dist/pypy/annotation/annrpython.py
==============================================================================
--- pypy/dist/pypy/annotation/annrpython.py	(original)
+++ pypy/dist/pypy/annotation/annrpython.py	Fri May 12 23:50:10 2006
@@ -34,6 +34,7 @@
         self.added_blocks = None # see processblock() below
         self.links_followed = {} # set of links that have ever been followed
         self.notify = {}        # {block: {positions-to-reflow-from-when-done}}
+        self.fixed_graphs = {}  # set of graphs not to annotate again
         # --- the following information is recorded for debugging only ---
         # --- and only if annotation.model.DEBUG is kept to True
         self.why_not_annotated = {} # {block: (exc_type, exc_value, traceback)}
@@ -333,7 +334,17 @@
             callpositions[callback] = True
 
         # generalize the function's input arguments
-        self.addpendingblock(graph, graph.startblock, inputcells, position_key)
+        if graph in self.fixed_graphs:
+            # special case for annotating/rtyping in several phases: calling
+            # a graph that has already been rtyped.  Safety-check the new
+            # annotations that are passed in, and don't annotate the old
+            # graph -- it's already low-level operations!
+            for a, s_newarg in zip(graph.getargs(), inputcells):
+                s_oldarg = self.binding(a)
+                assert s_oldarg.contains(s_newarg)
+        else:
+            self.addpendingblock(graph, graph.startblock, inputcells,
+                                 position_key)
 
         # get the (current) return value
         v = graph.getreturnvar()

Modified: pypy/dist/pypy/rpython/rtyper.py
==============================================================================
--- pypy/dist/pypy/rpython/rtyper.py	(original)
+++ pypy/dist/pypy/rpython/rtyper.py	Fri May 12 23:50:10 2006
@@ -289,6 +289,9 @@
         return LowLevelOpList(self, block)
 
     def specialize_block(self, block):
+        graph = self.annotator.annotated[block]
+        self.annotator.fixed_graphs[graph] = True
+
         # give the best possible types to the input args
         try:
             self.setup_block_entry(block)

Modified: pypy/dist/pypy/translator/stackless/code.py
==============================================================================
--- pypy/dist/pypy/translator/stackless/code.py	(original)
+++ pypy/dist/pypy/translator/stackless/code.py	Fri May 12 23:50:10 2006
@@ -4,6 +4,8 @@
 from pypy.translator.stackless import frame
 from pypy.translator.stackless.frame import STATE_HEADER, SAVED_REFERENCE
 
+EMPTY_STATE = frame.make_state_header_type('empty_state')
+
 # ____________________________________________________________
 
 SWITCH_STATE = frame.make_state_header_type('switch_state',
@@ -22,14 +24,17 @@
     elif global_state.restart_substate == 0:
         # STATE 0: we didn't do anything so far, but the stack is unwound
         global_state.restart_substate = -1
-        # grab the frame corresponding to ourself, and prepare it for
-        # the future switch() back, which will go to STATE 1 below
-        sourcestate = global_state.top
-        sourcestate.f_restart = INDEX_SWITCH + 1
+        # grab the frame corresponding to ourself
         # the 'targetstate' local is garbage here, it must be read back from
         # 's.c' where we saved it by the normal entry point above
-        s = lltype.cast_pointer(lltype.Ptr(SWITCH_STATE), sourcestate)
+        mystate = global_state.top
+        s = lltype.cast_pointer(lltype.Ptr(SWITCH_STATE), mystate)
         targetstate = lltype.cast_opaque_ptr(lltype.Ptr(STATE_HEADER), s.c)
+        # prepare a new saved state for the future switch() back,
+        # which will go to STATE 1 below
+        sourcestate = lltype.malloc(EMPTY_STATE).header
+        sourcestate.f_back = mystate.f_back
+        sourcestate.f_restart = INDEX_SWITCH + 1
         global_state.top = targetstate
         global_state.retval_ref = lltype.cast_opaque_ptr(SAVED_REFERENCE,
                                                          sourcestate)
@@ -45,7 +50,15 @@
                                # with the source state as return value
 ll_frame_switch.stackless_explicit = True
 
-INDEX_SWITCH = frame.RestartInfo.add_prebuilt(ll_frame_switch, 2)
+INDEX_SWITCH = frame.RestartInfo.add_prebuilt(ll_frame_switch,
+                                              [SWITCH_STATE, EMPTY_STATE])
+
+# ____________________________________________________________
+
+def ll_frame_clone(oldstate):
+    oldframe = lltype.cast_opaque_ptr(lltype.Ptr(STATE_HEADER), oldstate)
+    newframe = frame.ll_frame_reccopy(oldframe)
+    return lltype.cast_opaque_ptr(frame.OPAQUE_STATE_HEADER_PTR, newframe)
 
 # ____________________________________________________________
 
@@ -54,7 +67,7 @@
         # normal entry point for yield_current_frame_to_caller()
         # first unwind the stack
         u = UnwindException()
-        s = lltype.malloc(STATE_HEADER)
+        s = lltype.malloc(EMPTY_STATE).header
         s.f_restart = INDEX_YCFTC
         add_frame_state(u, s)
         raise u   # this goes to 'STATE 0' below
@@ -67,7 +80,7 @@
         caller_state = our_caller_state.f_back
         # when our immediate caller finishes (which is later, when the
         # tasklet finishes), then we will jump to 'STATE 1' below
-        endstate = lltype.malloc(STATE_HEADER)
+        endstate = lltype.malloc(EMPTY_STATE).header
         endstate.f_restart = INDEX_YCFTC + 1
         our_caller_state.f_back = endstate
         global_state.top = caller_state
@@ -97,7 +110,8 @@
 
 yield_current_frame_to_caller.stackless_explicit = True
 
-INDEX_YCFTC = frame.RestartInfo.add_prebuilt(yield_current_frame_to_caller, 2)
+INDEX_YCFTC = frame.RestartInfo.add_prebuilt(yield_current_frame_to_caller,
+                                             [EMPTY_STATE, EMPTY_STATE])
 
 # ____________________________________________________________
 
@@ -106,7 +120,7 @@
         # normal entry point for stack_frames_depth()
         # first unwind the stack
         u = UnwindException()
-        s = lltype.malloc(STATE_HEADER)
+        s = lltype.malloc(EMPTY_STATE).header
         s.f_restart = INDEX_DEPTH
         add_frame_state(u, s)
         raise u    # goes to STATE 0 below
@@ -122,7 +136,8 @@
         return depth
 stack_frames_depth.stackless_explicit = True
 
-INDEX_DEPTH = frame.RestartInfo.add_prebuilt(stack_frames_depth, 1)
+INDEX_DEPTH = frame.RestartInfo.add_prebuilt(stack_frames_depth,
+                                             [EMPTY_STATE])
 
 # ____________________________________________________________
 
@@ -131,7 +146,7 @@
         # normal entry point for stack_frames_depth()
         # first unwind the stack in the usual way
         u = UnwindException()
-        s = lltype.malloc(STATE_HEADER)
+        s = lltype.malloc(EMPTY_STATE).header
         s.f_restart = INDEX_UNWIND
         add_frame_state(u, s)
         raise u    # goes to STATE 0 below
@@ -141,7 +156,8 @@
         global_state.restart_substate = -1
 ll_stack_unwind.stackless_explicit = True
 
-INDEX_UNWIND = frame.RestartInfo.add_prebuilt(ll_stack_unwind, 1)
+INDEX_UNWIND = frame.RestartInfo.add_prebuilt(ll_stack_unwind,
+                                              [EMPTY_STATE])
 
 # ____________________________________________________________
 
@@ -200,8 +216,7 @@
     
     while True:
         back = pending.f_back
-        decoded = frame.decodestate(global_state.masterarray,
-                                    pending.f_restart)
+        decoded = frame.decodestate(pending.f_restart)
         (fn, global_state.restart_substate, retval_type) = decoded
         try:
             call_function(fn, retval_type)

Modified: pypy/dist/pypy/translator/stackless/frame.py
==============================================================================
--- pypy/dist/pypy/translator/stackless/frame.py	(original)
+++ pypy/dist/pypy/translator/stackless/frame.py	Fri May 12 23:50:10 2006
@@ -1,7 +1,11 @@
 from pypy.rpython.lltypesystem import lltype, llmemory
 from pypy.rpython import extfunctable
 from pypy.rpython.typesystem import getfunctionptr
+from pypy.rpython.annlowlevel import annotate_lowlevel_helper
 from pypy.objspace.flow.model import FunctionGraph
+from pypy.tool.sourcetools import compile2
+from pypy.annotation import model as annmodel
+from pypy.rpython.annlowlevel import MixLevelHelperAnnotator
 
 # ____________________________________________________________
 # generic data types
@@ -59,39 +63,49 @@
 
 
 def make_state_header_type(name, *fields):
-##    source = ['def ll_reccopy_%s(frame):' % name,
-##              '    if frame.f_back:'
-##              '        prev = frame.f_back.XXX',
-##              '    newframe = lltype.malloc(lltype.typeOf(FRAME))',
-##              '    newframe.']
-    
-##    copynames = [name for (name, _) in fields]
-##    copynames.append('header.restartstate')
-##    copynames.append('header.function')
-##    copynames.append('header.retval_type')
-##    for name in copynames:
-##        source.append('    newframe.%s = frame.%s' % (name, name))
-##    source.append('    return newframe')
-##    source.append('')
-##    miniglobals = {'lltype': lltype}
-##    exec compile2('\n'.join(source)) in miniglobals
-##    extras = {
-##        'adtmeths': {'reccopy': miniglobals['ll_frame_reccopy']}
-##        }
-    return lltype.GcStruct(name,
-                           ('header', STATE_HEADER),
-                           *fields)
+    fnname = 'll_reccopy_%s' % (name,)
+    source = ['def %s(frame):' % (fnname,),
+              '    frame = lltype.cast_pointer(lltype.Ptr(FRAME), frame)',
+              '    newframe = lltype.malloc(FRAME)',
+              '    if frame.header.f_back:',
+              '        newframe.header.f_back = ll_frame_reccopy(',
+              '                                     frame.header.f_back)',
+              '    newframe.header.f_restart = frame.header.f_restart']
+    for name, _ in fields:
+        source.append('    newframe.%s = frame.%s' % (name, name))
+    source.append('    return lltype.cast_pointer(lltype.Ptr(STATE_HEADER),')
+    source.append('                               newframe)')
+    source.append('')
+    miniglobals = {'lltype': lltype,
+                   'll_frame_reccopy': ll_frame_reccopy,
+                   'STATE_HEADER': STATE_HEADER,
+                   }
+    exec compile2('\n'.join(source)) in miniglobals
+    extras = {
+        'adtmeths': {'reccopy': miniglobals[fnname]}
+        }
+    FRAME = lltype.GcStruct(name,
+                            ('header', STATE_HEADER),
+                            *fields, **extras)
+    miniglobals['FRAME'] = FRAME
+    return FRAME
 
 # ____________________________________________________________
 # master array giving information about the restart points
 # (STATE_HEADER.frameinfo is an index into this array)
 
+RECCOPY_FUNC = lltype.FuncType([lltype.Ptr(STATE_HEADER)],
+                               lltype.Ptr(STATE_HEADER))
+
 FRAME_INFO = lltype.Struct('frame_info',
-                           ('fnaddr', llmemory.Address),
-                           ('info',   lltype.Signed))
+                           ('fnaddr',  llmemory.Address),
+                           ('info',    lltype.Signed),
+                           ('reccopy', lltype.Ptr(RECCOPY_FUNC)))
 FRAME_INFO_ARRAY = lltype.Array(FRAME_INFO)
 
-def decodestate(masterarray, index):
+def decodestate(index):
+    from pypy.translator.stackless.code import global_state
+    masterarray = global_state.masterarray
     finfo = masterarray[index]
     if finfo.fnaddr:
         restartstate = 0
@@ -103,22 +117,28 @@
             finfo.info)    # retval_type
 decodestate.stackless_explicit = True
 
+def ll_frame_reccopy(frame):
+    from pypy.translator.stackless.code import global_state
+    masterarray = global_state.masterarray
+    finfo = masterarray[frame.f_restart]
+    return finfo.reccopy(frame)
+
 
 class RestartInfo(object):
     __slots__ = ['func_or_graph',
                  'first_index',
-                 'nb_restart_states']
+                 'frame_types']
 
-    def __init__(self, func_or_graph, first_index, nb_restart_states):
+    def __init__(self, func_or_graph, first_index, frame_types):
         self.func_or_graph = func_or_graph
         self.first_index = first_index
-        self.nb_restart_states = nb_restart_states
+        self.frame_types = frame_types
 
     def compress(self, rtyper, masterarray):
-        if self.nb_restart_states > 0:
+        if self.frame_types:
+            bk = rtyper.annotator.bookkeeper
             graph = self.func_or_graph
             if not isinstance(graph, FunctionGraph):
-                bk = rtyper.annotator.bookkeeper
                 graph = bk.getdesc(graph).getuniquegraph()
             funcptr = getfunctionptr(graph)
             rettype = lltype.typeOf(funcptr).TO.RESULT
@@ -127,18 +147,26 @@
             finfo = masterarray[self.first_index]
             finfo.fnaddr = llmemory.cast_ptr_to_adr(funcptr)
             finfo.info = retval_type
-            for i in range(1, self.nb_restart_states):
+            for i in range(1, len(self.frame_types)):
                 finfo = masterarray[self.first_index+i]
                 finfo.info = i
+            for i in range(len(self.frame_types)):
+                reccopy = self.frame_types[i].reccopy
+                s_header = annmodel.SomePtr(lltype.Ptr(STATE_HEADER))
+                mixlevelannotator = MixLevelHelperAnnotator(rtyper)
+                fnptr = mixlevelannotator.delayedfunction(reccopy, [s_header],
+                                                          s_header)
+                mixlevelannotator.finish()
+                masterarray[self.first_index+i].reccopy = fnptr
 
     prebuilt = []
     prebuiltindex = 0
 
-    def add_prebuilt(cls, func, nb_restart_states):
+    def add_prebuilt(cls, func, frame_types):
         assert func.stackless_explicit    # did you forget this flag?
         n = cls.prebuiltindex
-        restart = cls(func, n, nb_restart_states)
+        restart = cls(func, n, frame_types)
         cls.prebuilt.append(restart)
-        cls.prebuiltindex += restart.nb_restart_states
+        cls.prebuiltindex += len(frame_types)
         return n
     add_prebuilt = classmethod(add_prebuilt)

Added: pypy/dist/pypy/translator/stackless/test/test_clone.py
==============================================================================
--- (empty file)
+++ pypy/dist/pypy/translator/stackless/test/test_clone.py	Fri May 12 23:50:10 2006
@@ -0,0 +1,40 @@
+from pypy.translator.stackless.test.test_transform import \
+     llinterp_stackless_function, run_stackless_function
+from pypy.rpython import rstack
+
+
+def test_simple():
+    def g(lst):
+        lst.append(1)
+        parent = rstack.yield_current_frame_to_caller()
+        # compute a bit
+        lst.append(3)
+        # switch back for the fork
+        parent = parent.switch()
+        lst.append(6)   # we are here twice!
+        return parent
+
+    def f():
+        lst = []
+        c = g(lst)
+        lst.append(2)
+        c1 = c.switch()
+        lst.append(4)
+        c2 = c1.clone()      # clone() here
+        lst.append(5)
+        end1 = c1.switch()
+        lst.append(7)
+        end2 = c2.switch()
+        lst.append(8)
+        assert not end1
+        assert not end2
+        n = 0
+        for i in lst:
+            n = n*10 + i
+        return n
+
+    data = llinterp_stackless_function(f)
+    assert data == 123456768
+
+    res = run_stackless_function(f)
+    assert res == 123456768

Modified: pypy/dist/pypy/translator/stackless/transform.py
==============================================================================
--- pypy/dist/pypy/translator/stackless/transform.py	(original)
+++ pypy/dist/pypy/translator/stackless/transform.py	Fri May 12 23:50:10 2006
@@ -187,6 +187,9 @@
             ll_stackless.ll_stackless_switch:
                 mixlevelannotator.constfunc(
                     code.ll_frame_switch, [s_StatePtr], s_StatePtr),
+            ll_stackless.ll_stackless_clone:
+                mixlevelannotator.constfunc(
+                    code.ll_frame_clone, [s_StatePtr], s_StatePtr),
             ll_stack.ll_stack_unwind:
                 mixlevelannotator.constfunc(
                     code.ll_stack_unwind, [], annmodel.s_None),
@@ -535,8 +538,9 @@
         return llops
 
     def generate_restart_infos(self, graph):
+        frame_types = [rp.frame_state_type for rp in self.resume_points]
         restartinfo = frame.RestartInfo(graph, self.restartinfoindex,
-                                        len(self.resume_points))
+                                        frame_types)
         self.restartinfos.append(restartinfo)
         self.restartinfoindex += len(self.resume_points)
 

Modified: pypy/dist/pypy/translator/unsimplify.py
==============================================================================
--- pypy/dist/pypy/translator/unsimplify.py	(original)
+++ pypy/dist/pypy/translator/unsimplify.py	Fri May 12 23:50:10 2006
@@ -7,7 +7,7 @@
     if translator is not None:
         annotator = translator.annotator
         if annotator is not None and v in annotator.bindings:
-            annotator.bindings[newvar] = annotator.bindings[v]
+            annotator.setbinding(newvar, annotator.bindings[v])
     if hasattr(v, 'concretetype'):
         newvar.concretetype = v.concretetype
     return newvar


From arigo at codespeak.net  Sat May 13 00:18:59 2006
From: arigo at codespeak.net (arigo at codespeak.net)
Date: Sat, 13 May 2006 00:18:59 +0200 (CEST)
Subject: [pypy-svn] r27158 - pypy/dist/pypy/translator/stackless
Message-ID: <20060512221859.47E2A100B4@code0.codespeak.net>

Author: arigo
Date: Sat May 13 00:18:58 2006
New Revision: 27158

Modified:
   pypy/dist/pypy/translator/stackless/frame.py
   pypy/dist/pypy/translator/stackless/transform.py
Log:
Order issues: discover new graphs and frame types for the stackless
helpers along the way during the stackless transformation.
(Apart from the few prebuilt ones, the RestartInfo instances
are now very short-lived, which makes them a bit strange).


Modified: pypy/dist/pypy/translator/stackless/frame.py
==============================================================================
--- pypy/dist/pypy/translator/stackless/frame.py	(original)
+++ pypy/dist/pypy/translator/stackless/frame.py	Sat May 13 00:18:58 2006
@@ -125,16 +125,12 @@
 
 
 class RestartInfo(object):
-    __slots__ = ['func_or_graph',
-                 'first_index',
-                 'frame_types']
 
-    def __init__(self, func_or_graph, first_index, frame_types):
+    def __init__(self, func_or_graph, frame_types):
         self.func_or_graph = func_or_graph
-        self.first_index = first_index
         self.frame_types = frame_types
 
-    def compress(self, rtyper, masterarray):
+    def compress(self, rtyper):
         if self.frame_types:
             bk = rtyper.annotator.bookkeeper
             graph = self.func_or_graph
@@ -144,12 +140,11 @@
             rettype = lltype.typeOf(funcptr).TO.RESULT
             retval_type = STORAGE_TYPES.index(storage_type(rettype))
 
-            finfo = masterarray[self.first_index]
-            finfo.fnaddr = llmemory.cast_ptr_to_adr(funcptr)
-            finfo.info = retval_type
+            result = [{'fnaddr': llmemory.cast_ptr_to_adr(funcptr),
+                       'info':   retval_type},
+                      ]
             for i in range(1, len(self.frame_types)):
-                finfo = masterarray[self.first_index+i]
-                finfo.info = i
+                result.append({'info': i})
             for i in range(len(self.frame_types)):
                 reccopy = self.frame_types[i].reccopy
                 s_header = annmodel.SomePtr(lltype.Ptr(STATE_HEADER))
@@ -157,15 +152,18 @@
                 fnptr = mixlevelannotator.delayedfunction(reccopy, [s_header],
                                                           s_header)
                 mixlevelannotator.finish()
-                masterarray[self.first_index+i].reccopy = fnptr
+                result[i]['reccopy'] = fnptr
+        else:
+            result = []
+        return result
 
     prebuilt = []
     prebuiltindex = 0
 
     def add_prebuilt(cls, func, frame_types):
         assert func.stackless_explicit    # did you forget this flag?
+        restart = cls(func, frame_types)
         n = cls.prebuiltindex
-        restart = cls(func, n, frame_types)
         cls.prebuilt.append(restart)
         cls.prebuiltindex += len(frame_types)
         return n

Modified: pypy/dist/pypy/translator/stackless/transform.py
==============================================================================
--- pypy/dist/pypy/translator/stackless/transform.py	(original)
+++ pypy/dist/pypy/translator/stackless/transform.py	Sat May 13 00:18:58 2006
@@ -120,8 +120,7 @@
         self.translator = translator
 
         self.frametyper = FrameTyper()
-        self.restartinfos = frame.RestartInfo.prebuilt[:]
-        self.restartinfoindex = frame.RestartInfo.prebuiltindex
+        self.masterarray1 = []
         self.curr_graph = None
         
         bk = translator.annotator.bookkeeper
@@ -215,6 +214,10 @@
         self.c_null_state = model.Constant(null_state,
                                            lltype.typeOf(null_state))
 
+        # register the prebuilt restartinfos
+        for restartinfo in frame.RestartInfo.prebuilt:
+            self.register_restart_info(restartinfo)
+
     def transform_all(self):
         for graph in self.translator.graphs:
             self.transform_graph(graph)
@@ -504,7 +507,7 @@
             [self.add_frame_state_ptr, var_exc, var_header],
             varoftype(lltype.Void)))
 
-        f_restart = self.restartinfoindex + len(self.resume_points)
+        f_restart = len(self.masterarray1) + len(self.resume_points)
         saveops.append(model.SpaceOperation(
             "setfield",
             [var_header, self.c_f_restart_name,
@@ -539,19 +542,23 @@
 
     def generate_restart_infos(self, graph):
         frame_types = [rp.frame_state_type for rp in self.resume_points]
-        restartinfo = frame.RestartInfo(graph, self.restartinfoindex,
-                                        frame_types)
-        self.restartinfos.append(restartinfo)
-        self.restartinfoindex += len(self.resume_points)
+        restartinfo = frame.RestartInfo(graph, frame_types)
+        self.register_restart_info(restartinfo)
+
+    def register_restart_info(self, restartinfo):
+        rtyper = self.translator.rtyper
+        for frame_info_dict in restartinfo.compress(rtyper):
+            self.masterarray1.append(frame_info_dict)
 
     def finish(self):
-        # compute the final masterarray
+        # compute the final masterarray by copying over the masterarray1,
+        # which is a list of dicts of attributes
         masterarray = lltype.malloc(frame.FRAME_INFO_ARRAY,
-                                    self.restartinfoindex,
+                                    len(self.masterarray1),
                                     immortal=True)
-        rtyper = self.translator.rtyper
-        for restartinfo in self.restartinfos:
-            restartinfo.compress(rtyper, masterarray)
+        for dst, src in zip(masterarray, self.masterarray1):
+            for key, value in src.items():
+                setattr(dst, key, value)
         # horrors in the same spirit as in rpython.memory.gctransform
         # (shorter, though)
         ll_global_state = self.ll_global_state.value


From arigo at codespeak.net  Sat May 13 11:10:24 2006
From: arigo at codespeak.net (arigo at codespeak.net)
Date: Sat, 13 May 2006 11:10:24 +0200 (CEST)
Subject: [pypy-svn] r27163 - pypy/dist/pypy/jit/llabstractinterp/test
Message-ID: <20060513091024.E45E9100AA@code0.codespeak.net>

Author: arigo
Date: Sat May 13 11:10:23 2006
New Revision: 27163

Modified:
   pypy/dist/pypy/jit/llabstractinterp/test/test_jit_tl.py
Log:
This test is again in-progress.  Recent changes made Void variables
show up, and the llabstractinterp crashes on them.


Modified: pypy/dist/pypy/jit/llabstractinterp/test/test_jit_tl.py
==============================================================================
--- pypy/dist/pypy/jit/llabstractinterp/test/test_jit_tl.py	(original)
+++ pypy/dist/pypy/jit/llabstractinterp/test/test_jit_tl.py	Sat May 13 11:10:23 2006
@@ -9,7 +9,7 @@
 from pypy.jit.llabstractinterp.test.test_llabstractinterp import summary
 #from pypy.translator.backendopt import inline
 
-#py.test.skip("in-progress")
+py.test.skip("not implementing: handling of Void values")
 
 def setup_module(mod):
     t = TranslationContext()


From cfbolz at codespeak.net  Sat May 13 12:06:45 2006
From: cfbolz at codespeak.net (cfbolz at codespeak.net)
Date: Sat, 13 May 2006 12:06:45 +0200 (CEST)
Subject: [pypy-svn] r27164 - in pypy/dist/pypy: rpython rpython/l3interp
	rpython/memory rpython/test translator/backendopt
Message-ID: <20060513100645.E130C100AA@code0.codespeak.net>

Author: cfbolz
Date: Sat May 13 12:06:42 2006
New Revision: 27164

Modified:
   pypy/dist/pypy/rpython/l3interp/convertgraph.py
   pypy/dist/pypy/rpython/memory/gctransform.py
   pypy/dist/pypy/rpython/objectmodel.py
   pypy/dist/pypy/rpython/test/test_objectmodel.py
   pypy/dist/pypy/translator/backendopt/all.py
Log:
add a __hash__ and a __cmp__ to symbolic to prevent bad things happening. of
course it did not actually help with the problem at hand :-(


Modified: pypy/dist/pypy/rpython/l3interp/convertgraph.py
==============================================================================
--- pypy/dist/pypy/rpython/l3interp/convertgraph.py	(original)
+++ pypy/dist/pypy/rpython/l3interp/convertgraph.py	Sat May 13 12:06:42 2006
@@ -82,11 +82,17 @@
                 value = fakeaddress(v.value)
             else:
                 value = v.value
-            try:
-                res = clist.index(value)
-            except ValueError:
-                res = len(clist)
-                clist.append(value)
+            for i, item in enumerate(clist):
+                # XXX hum, hum. The fact that symbolics are not comparable
+                # makes this ugly thing necessary :-(
+                try:
+                    if item == value:
+                        return i
+                except TypeError:
+                    if item is value:
+                        return i
+            res = len(clist)
+            clist.append(value)
             return res
         else:
             position = self.var2stack[v]
@@ -94,9 +100,10 @@
 
     def getoffset(self, offset):
         clist = self.constants['int']
-        try:
-            res = clist.index(offset)
-        except ValueError:
+        for i, item in enumerate(clist):
+            if item is offset:
+                return i
+        else:
             res = len(clist)
             clist.append(offset)
         return res

Modified: pypy/dist/pypy/rpython/memory/gctransform.py
==============================================================================
--- pypy/dist/pypy/rpython/memory/gctransform.py	(original)
+++ pypy/dist/pypy/rpython/memory/gctransform.py	Sat May 13 12:06:42 2006
@@ -907,7 +907,7 @@
             self.type_info_list.append(info)
             self.id_of_type[TYPE] = type_id
             offsets = offsets_to_gc_pointers(TYPE)
-            info["ofstoptrs"] = self.offsets2table(offsets)
+            info["ofstoptrs"] = self.offsets2table(offsets, TYPE)
             if not TYPE._is_varsize():
                 info["fixedsize"] = llmemory.sizeof(TYPE)
                 info["ofstolength"] = -1
@@ -933,10 +933,10 @@
                 assert isinstance(ARRAY, lltype.Array)
                 if ARRAY.OF != lltype.Void:
                     offsets = offsets_to_gc_pointers(ARRAY.OF)
-                    info["varofstoptrs"] = self.offsets2table(offsets)
+                    info["varofstoptrs"] = self.offsets2table(offsets, ARRAY.OF)
                     info["varitemsize"] = llmemory.sizeof(ARRAY.OF)
                 else:
-                    info["varofstoptrs"] = self.offsets2table(())
+                    info["varofstoptrs"] = self.offsets2table((), lltype.Void)
                     info["varitemsize"] = 0
             return type_id
 
@@ -952,16 +952,15 @@
                 for a in gc_pointers_inside(value, llmemory.fakeaddress(value)):
                     self.addresses_of_static_ptrs_in_nongc.append(a)
 
-    def offsets2table(self, offsets):
-        key = tuple(offsets)
+    def offsets2table(self, offsets, TYPE):
         try:
-            return self.offsettable_cache[key]
+            return self.offsettable_cache[TYPE]
         except KeyError:
             cachedarray = lltype.malloc(self.gcdata.OFFSETS_TO_GC_PTR,
                                         len(offsets), immortal=True)
             for i, value in enumerate(offsets):
                 cachedarray[i] = value
-            self.offsettable_cache[key] = cachedarray
+            self.offsettable_cache[TYPE] = cachedarray
             return cachedarray
 
     def finish(self):

Modified: pypy/dist/pypy/rpython/objectmodel.py
==============================================================================
--- pypy/dist/pypy/rpython/objectmodel.py	(original)
+++ pypy/dist/pypy/rpython/objectmodel.py	Sat May 13 12:06:42 2006
@@ -13,6 +13,12 @@
     def lltype(self):
         return None
 
+    def __cmp__(self, other):
+        raise TypeError("Symbolics can not be compared!")
+
+    def __hash__(self):
+        raise TypeError("Symbolics are not hashable!")
+
 class ComputedIntSymbolic(Symbolic):
 
     def __init__(self, compute_fn):

Modified: pypy/dist/pypy/rpython/test/test_objectmodel.py
==============================================================================
--- pypy/dist/pypy/rpython/test/test_objectmodel.py	(original)
+++ pypy/dist/pypy/rpython/test/test_objectmodel.py	Sat May 13 12:06:42 2006
@@ -266,3 +266,12 @@
 
     assert A(12098).value == 12098
     assert A(12098).getvalue() == 12098
+
+def test_symbolic():
+    
+
+def test_symbolic_raises():
+    s1 = Symbolic()
+    s2 = Symbolic()
+    py.test.raises(TypeError, "s1 < s2")
+    py.test.raises(TypeError, "hash(s1)")

Modified: pypy/dist/pypy/translator/backendopt/all.py
==============================================================================
--- pypy/dist/pypy/translator/backendopt/all.py	(original)
+++ pypy/dist/pypy/translator/backendopt/all.py	Sat May 13 12:06:42 2006
@@ -16,7 +16,7 @@
                                       inline_threshold=1,
                                       mallocs=True,
                                       merge_if_blocks_to_switch=True,
-                                      propagate=False,
+                                      propagate=True,
                                       heap2stack=False,
                                       clever_malloc_removal=False):
 


From antocuni at codespeak.net  Sat May 13 13:46:52 2006
From: antocuni at codespeak.net (antocuni at codespeak.net)
Date: Sat, 13 May 2006 13:46:52 +0200 (CEST)
Subject: [pypy-svn] r27165 - pypy/dist/pypy/rpython/ootypesystem/test
Message-ID: <20060513114652.676871007B@code0.codespeak.net>

Author: antocuni
Date: Sat May 13 13:46:43 2006
New Revision: 27165

Modified:
   pypy/dist/pypy/rpython/ootypesystem/test/test_ooann.py
Log:
Added a test for List.



Modified: pypy/dist/pypy/rpython/ootypesystem/test/test_ooann.py
==============================================================================
--- pypy/dist/pypy/rpython/ootypesystem/test/test_ooann.py	(original)
+++ pypy/dist/pypy/rpython/ootypesystem/test/test_ooann.py	Sat May 13 13:46:43 2006
@@ -185,3 +185,16 @@
     s = a.build_types(oof, [bool])
     assert isinstance(s, annmodel.SomeBool)
     assert not s.is_constant()
+
+def test_list():
+    L = List(Signed)
+    def oof():
+        l = new(L)
+        l._ll_resize(42)
+        return l
+
+    a = RPythonAnnotator()
+    s = a.build_types(oof, [])
+    #a.translator.view()
+    
+    assert s == annmodel.SomeOOInstance(L)


From antocuni at codespeak.net  Sat May 13 14:30:29 2006
From: antocuni at codespeak.net (antocuni at codespeak.net)
Date: Sat, 13 May 2006 14:30:29 +0200 (CEST)
Subject: [pypy-svn] r27166 - pypy/dist/pypy/rpython/ootypesystem/test
Message-ID: <20060513123029.92D2D100A9@code0.codespeak.net>

Author: antocuni
Date: Sat May 13 14:30:21 2006
New Revision: 27166

Modified:
   pypy/dist/pypy/rpython/ootypesystem/test/test_ooann.py
   pypy/dist/pypy/rpython/ootypesystem/test/test_oortype.py
Log:
Add some tests for String annotation and a failing test for oostring().



Modified: pypy/dist/pypy/rpython/ootypesystem/test/test_ooann.py
==============================================================================
--- pypy/dist/pypy/rpython/ootypesystem/test/test_ooann.py	(original)
+++ pypy/dist/pypy/rpython/ootypesystem/test/test_ooann.py	Sat May 13 14:30:21 2006
@@ -196,5 +196,13 @@
     a = RPythonAnnotator()
     s = a.build_types(oof, [])
     #a.translator.view()
-    
+
     assert s == annmodel.SomeOOInstance(L)
+
+def test_string():
+    def oof():
+        return new(String)
+
+    a = RPythonAnnotator()
+    s = a.build_types(oof, [])
+    assert s == annmodel.SomeOOInstance(String)

Modified: pypy/dist/pypy/rpython/ootypesystem/test/test_oortype.py
==============================================================================
--- pypy/dist/pypy/rpython/ootypesystem/test/test_oortype.py	(original)
+++ pypy/dist/pypy/rpython/ootypesystem/test/test_oortype.py	Sat May 13 14:30:21 2006
@@ -187,3 +187,18 @@
     INST = graph.getreturnvar().concretetype
     assert rtyper.exceptiondata.is_exception_instance(INST)
 
+def test_string_annotation():
+    def oof(lst):
+        return lst.ll_strlen()
+
+    s = new(String)
+    assert interpret(oof, [s], type_system='ootype') == 0
+    s = make_string('foo')
+    assert interpret(oof, [s], type_system='ootype') == 3
+
+def test_oostring():
+    def oof(ch):
+        return oostring(ch)
+
+    ch = 'a'
+    res = interpret(oof, [ch], type_system='ootype')


From antocuni at codespeak.net  Sat May 13 14:34:07 2006
From: antocuni at codespeak.net (antocuni at codespeak.net)
Date: Sat, 13 May 2006 14:34:07 +0200 (CEST)
Subject: [pypy-svn] r27167 - in pypy/dist/pypy/rpython: . ootypesystem test
Message-ID: <20060513123407.0BD32100A9@code0.codespeak.net>

Author: antocuni
Date: Sat May 13 14:33:49 2006
New Revision: 27167

Modified:
   pypy/dist/pypy/rpython/llinterp.py
   pypy/dist/pypy/rpython/ootypesystem/ootype.py
   pypy/dist/pypy/rpython/ootypesystem/rbuiltin.py
   pypy/dist/pypy/rpython/ootypesystem/rstr.py
   pypy/dist/pypy/rpython/test/test_rstr.py
Log:
Added a new operation 'oostring'



Modified: pypy/dist/pypy/rpython/llinterp.py
==============================================================================
--- pypy/dist/pypy/rpython/llinterp.py	(original)
+++ pypy/dist/pypy/rpython/llinterp.py	Sat May 13 14:33:49 2006
@@ -1001,6 +1001,8 @@
     def op_ooidentityhash(self, inst):
         return ootype.ooidentityhash(inst)
 
+    def op_oostring(self, obj):
+        return ootype.oostring(obj)
 
 class Tracer(object):
     Counter = 0

Modified: pypy/dist/pypy/rpython/ootypesystem/ootype.py
==============================================================================
--- pypy/dist/pypy/rpython/ootypesystem/ootype.py	(original)
+++ pypy/dist/pypy/rpython/ootypesystem/ootype.py	Sat May 13 14:33:49 2006
@@ -1056,6 +1056,10 @@
     assert isinstance(typeOf(inst), (Instance, Record))
     return inst._identityhash()
 
+def oostring(obj):
+    "Convert char, int and str to str"
+    return make_string(str(obj))
+
 def setItemType(LIST, ITEMTYPE):
     return LIST._set_itemtype(ITEMTYPE)
 

Modified: pypy/dist/pypy/rpython/ootypesystem/rbuiltin.py
==============================================================================
--- pypy/dist/pypy/rpython/ootypesystem/rbuiltin.py	(original)
+++ pypy/dist/pypy/rpython/ootypesystem/rbuiltin.py	Sat May 13 14:33:49 2006
@@ -57,6 +57,12 @@
     else:
         raise TyperError("XXX missing impl of isinstance(x, variable)")
 
+def rtype_oostring(hop):
+    assert isinstance(hop.args_s[0],(annmodel.SomeInteger,
+                                     annmodel.SomeChar,
+                                     annmodel.SomeString))
+    return hop.genop('oostring', hop.args_v, resulttype = ootype.String)
+
 
 BUILTIN_TYPER = {}
 BUILTIN_TYPER[ootype.new] = rtype_new
@@ -66,3 +72,4 @@
 BUILTIN_TYPER[ootype.runtimenew] = rtype_runtimenew
 BUILTIN_TYPER[ootype.ooidentityhash] = rtype_ooidentityhash
 BUILTIN_TYPER[isinstance] = rtype_builtin_isinstance
+BUILTIN_TYPER[ootype.oostring] = rtype_oostring

Modified: pypy/dist/pypy/rpython/ootypesystem/rstr.py
==============================================================================
--- pypy/dist/pypy/rpython/ootypesystem/rstr.py	(original)
+++ pypy/dist/pypy/rpython/ootypesystem/rstr.py	Sat May 13 14:33:49 2006
@@ -60,6 +60,8 @@
     def ll_strconcat(s1, s2):
         return s1.ll_strconcat(s2)
 
+    def ll_chr2str(ch):
+        return ootype.oostring(ch)
 
 string_repr = StringRepr()
 char_repr = 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	Sat May 13 14:33:49 2006
@@ -101,7 +101,6 @@
             assert res is True
         
     def test_char_constant(self):
-        self._skip_oo('conversion char-->string')
         def fn(s):
             return s + '.'
         res = self.interpret(fn, ['x'])


From arigo at codespeak.net  Sat May 13 14:35:01 2006
From: arigo at codespeak.net (arigo at codespeak.net)
Date: Sat, 13 May 2006 14:35:01 +0200 (CEST)
Subject: [pypy-svn] r27168 - in pypy/dist/pypy: rpython rpython/memory
	rpython/module translator/c translator/c/test
	translator/stackless translator/stackless/test
Message-ID: <20060513123501.F1237100A9@code0.codespeak.net>

Author: arigo
Date: Sat May 13 14:34:58 2006
New Revision: 27168

Modified:
   pypy/dist/pypy/rpython/extfunctable.py
   pypy/dist/pypy/rpython/memory/gctransform.py
   pypy/dist/pypy/rpython/module/ll_stack.py
   pypy/dist/pypy/rpython/rstack.py
   pypy/dist/pypy/translator/c/database.py
   pypy/dist/pypy/translator/c/gc.py
   pypy/dist/pypy/translator/c/genc.py
   pypy/dist/pypy/translator/c/test/test_newgc.py
   pypy/dist/pypy/translator/stackless/code.py
   pypy/dist/pypy/translator/stackless/test/test_depth.py
   pypy/dist/pypy/translator/stackless/transform.py
Log:
(arigo, a bit of pedronis)  Partial progress on integrating the Stackless
transformer with the Framework GC.



Modified: pypy/dist/pypy/rpython/extfunctable.py
==============================================================================
--- pypy/dist/pypy/rpython/extfunctable.py	(original)
+++ pypy/dist/pypy/rpython/extfunctable.py	Sat May 13 14:34:58 2006
@@ -250,7 +250,7 @@
 declare(rstack.stack_frames_depth, int, 'll_stackless/stack_frames_depth')
 declare(rstack.stack_too_big, bool, 'll_stack/too_big')
 declare(rstack.stack_check, noneannotation, 'll_stack/check')
-declare(rstack.stack_unwind, noneannotation, 'll_stack/unwind')
+declare(rstack.stack_unwind, rstack.frame_stack_top, 'll_stack/unwind')
 frametop_type_info = declaregcptrtype(rstack.frame_stack_top,'frame_stack_top',
                                         switch = (rstack.frame_stack_top,
                                                   'll_stackless/switch'),

Modified: pypy/dist/pypy/rpython/memory/gctransform.py
==============================================================================
--- pypy/dist/pypy/rpython/memory/gctransform.py	(original)
+++ pypy/dist/pypy/rpython/memory/gctransform.py	Sat May 13 14:34:58 2006
@@ -723,6 +723,7 @@
         return op.opname in ("malloc", "malloc_varsize", "gc__collect")
 
 class FrameworkGCTransformer(GCTransformer):
+    use_stackless = False
 
     def __init__(self, translator):
         from pypy.rpython.memory.support import get_address_linked_list
@@ -731,7 +732,6 @@
         class GCData(object):
             from pypy.rpython.memory.gc import MarkSweepGC as GCClass
             startheapsize = 8*1024*1024 # XXX adjust
-            rootstacksize = 640*1024    # XXX adjust
 
             # types of the GC information tables
             OFFSETS_TO_GC_PTR = lltype.Array(lltype.Signed)
@@ -772,7 +772,12 @@
                                                immortal=True)
         gcdata.static_roots = lltype.malloc(lltype.Array(llmemory.Address), 0,
                                             immortal=True)
-        gcdata.static_root_start = gcdata.static_root_end = llmemory.cast_ptr_to_adr(gcdata.static_roots)
+        # initialize the following two fields with a random non-NULL address,
+        # to make the annotator happy.  The fields are patched in finish()
+        # to point to a real array (not 'static_roots', another one).
+        a_random_address = llmemory.cast_ptr_to_adr(gcdata.type_info_table)
+        gcdata.static_root_start = a_random_address   # patched in finish()
+        gcdata.static_root_end = a_random_address     # patched in finish()
         self.gcdata = gcdata
         self.type_info_list = []
         self.id_of_type = {}      # {LLTYPE: type_id}
@@ -783,32 +788,13 @@
         self.malloc_fnptr_cache = {}
 
         sizeofaddr = llmemory.sizeof(llmemory.Address)
-        from pypy.rpython.memory.lladdress import NULL
 
-        class StackRootIterator:
-            _alloc_flavor_ = 'raw'
-            def __init__(self):
-                self.stack_current = gcdata.root_stack_top
-                self.static_current = gcdata.static_root_start
-
-            def pop(self):
-                while self.static_current != gcdata.static_root_end:
-                    result = self.static_current
-                    self.static_current += sizeofaddr
-                    if result.address[0].address[0] != NULL:
-                        return result.address[0]
-                while self.stack_current != gcdata.root_stack_base:
-                    self.stack_current -= sizeofaddr
-                    if self.stack_current.address[0] != NULL:
-                        return self.stack_current
-                return NULL
+        StackRootIterator = self.build_stack_root_iterator()
         gcdata.gc = GCData.GCClass(AddressLinkedList, GCData.startheapsize, StackRootIterator)
 
         def frameworkgc_setup():
             # run-time initialization code
-            stackbase = lladdress.raw_malloc(GCData.rootstacksize)
-            gcdata.root_stack_top  = stackbase
-            gcdata.root_stack_base = stackbase
+            StackRootIterator.setup_root_stack()
             gcdata.gc.setup()
             gcdata.gc.set_query_functions(
                 q_is_varsize,
@@ -818,25 +804,6 @@
                 q_varsize_offset_to_variable_part,
                 q_varsize_offset_to_length,
                 q_varsize_offsets_to_gcpointers_in_var_part)
-            i = 0
-            while i < len(gcdata.static_roots):
-                push_root(gcdata.static_roots[i])
-                i += 1
-
-        def push_root(addr):
-            top = gcdata.root_stack_top
-            top.address[0] = addr
-            gcdata.root_stack_top = top + sizeofaddr
-
-        # XXX specific to mark and sweep
-        def pop_root():
-            gcdata.root_stack_top -= sizeofaddr
-        # this should really be:
-        # def pop_root():
-        #     top = gcdata.root_stack_top - sizeofaddr
-        #     result = top.address[0]
-        #     gcdata.root_stack_top = top
-        #     return result
 
         bk = self.translator.annotator.bookkeeper
 
@@ -859,11 +826,17 @@
         annhelper = annlowlevel.MixLevelHelperAnnotator(self.translator.rtyper)
         frameworkgc_setup_graph = annhelper.getgraph(frameworkgc_setup, [],
                                                      annmodel.s_None)
-        push_root_graph = annhelper.getgraph(push_root,
-                                             [annmodel.SomeAddress()],
-                                             annmodel.s_None)
-        pop_root_graph = annhelper.getgraph(pop_root, [],
-                                            annmodel.s_None)
+        if StackRootIterator.push_root is None:
+            push_root_graph = None
+        else:
+            push_root_graph = annhelper.getgraph(StackRootIterator.push_root,
+                                                 [annmodel.SomeAddress()],
+                                                 annmodel.s_None)
+        if StackRootIterator.pop_root is None:
+            pop_root_graph = None
+        else:
+            pop_root_graph = annhelper.getgraph(StackRootIterator.pop_root, [],
+                                                annmodel.s_None)
 
         classdef = bk.getuniqueclassdef(GCData.GCClass)
         s_gcdata = annmodel.SomeInstance(classdef)
@@ -879,10 +852,16 @@
             [s_gcdata], annmodel.s_None)
         annhelper.finish()   # at this point, annotate all mix-level helpers
         self.frameworkgc_setup_ptr = self.graph2funcptr(frameworkgc_setup_graph)
-        self.push_root_ptr = self.graph2funcptr(push_root_graph)
-        self.graphs_to_inline[push_root_graph] = True
-        self.pop_root_ptr = self.graph2funcptr(pop_root_graph)
-        self.graphs_to_inline[pop_root_graph] = True
+        if push_root_graph is None:
+            self.push_root_ptr = None
+        else:
+            self.push_root_ptr = self.graph2funcptr(push_root_graph)
+            self.graphs_to_inline[push_root_graph] = True
+        if pop_root_graph is None:
+            self.pop_root_ptr = None
+        else:
+            self.pop_root_ptr = self.graph2funcptr(pop_root_graph)
+            self.graphs_to_inline[pop_root_graph] = True
         self.malloc_fixedsize_ptr = self.graph2funcptr(malloc_fixedsize_graph)
         self.malloc_varsize_ptr = self.graph2funcptr(malloc_varsize_graph)
         self.collect_ptr = self.graph2funcptr(collect_graph)
@@ -890,6 +869,51 @@
         self.collect_analyzer = CollectAnalyzer(self.translator)
         self.collect_analyzer.analyze_all()
 
+    def build_stack_root_iterator(self):
+        rootstacksize = 640*1024    # XXX adjust
+        gcdata = self.gcdata
+        sizeofaddr = llmemory.sizeof(llmemory.Address)
+
+        class StackRootIterator:
+            _alloc_flavor_ = 'raw'
+            def setup_root_stack():
+                stackbase = lladdress.raw_malloc(rootstacksize)
+                gcdata.root_stack_top  = stackbase
+                gcdata.root_stack_base = stackbase
+                i = 0
+                while i < len(gcdata.static_roots):
+                    StackRootIterator.push_root(gcdata.static_roots[i])
+                    i += 1
+            setup_root_stack = staticmethod(setup_root_stack)
+
+            def push_root(addr):
+                top = gcdata.root_stack_top
+                top.address[0] = addr
+                gcdata.root_stack_top = top + sizeofaddr
+            push_root = staticmethod(push_root)
+
+            def pop_root():
+                gcdata.root_stack_top -= sizeofaddr
+            pop_root = staticmethod(pop_root)
+
+            def __init__(self):
+                self.stack_current = gcdata.root_stack_top
+                self.static_current = gcdata.static_root_start
+
+            def pop(self):
+                while self.static_current != gcdata.static_root_end:
+                    result = self.static_current
+                    self.static_current += sizeofaddr
+                    if result.address[0].address[0] != llmemory.NULL:
+                        return result.address[0]
+                while self.stack_current != gcdata.root_stack_base:
+                    self.stack_current -= sizeofaddr
+                    if self.stack_current.address[0] != llmemory.NULL:
+                        return self.stack_current
+                return llmemory.NULL
+
+        return StackRootIterator
+
     def graph2funcptr(self, graph):
         self.need_minimal_transform(graph)
         return const_funcptr_fromgraph(graph)
@@ -1080,6 +1104,8 @@
         return []
 
     def push_roots(self, vars):
+        if self.push_root_ptr is None:
+            return
         for var in vars:
             v = varoftype(llmemory.Address)
             yield SpaceOperation("cast_ptr_to_adr", [var], v)
@@ -1087,6 +1113,8 @@
                                  varoftype(lltype.Void))
 
     def pop_roots(self, vars):
+        if self.pop_root_ptr is None:
+            return
         for var in vars[::-1]:
             v = varoftype(lltype.Void)
             # XXX specific to non-moving collectors
@@ -1106,7 +1134,11 @@
             baseofs = llmemory.offsetof(TYPE, name)
             suboffsets = offsets_to_gc_pointers(FIELD)
             for s in suboffsets:
-                if s == 0:
+                try:
+                    knownzero = s == 0
+                except TypeError:
+                    knownzero = False
+                if knownzero:
                     offsets.append(baseofs)
                 else:
                     offsets.append(baseofs + s)
@@ -1115,6 +1147,49 @@
         offsets.append(0)
     return offsets
 
+
+class StacklessFrameworkGCTransformer(FrameworkGCTransformer):
+    use_stackless = True
+
+    def build_stack_root_iterator(self):
+        from pypy.rpython.rstack import stack_unwind
+        sizeofaddr = llmemory.sizeof(llmemory.Address)
+        gcdata = self.gcdata
+
+        class StackRootIterator:
+            _alloc_flavor_ = 'raw'
+
+            def setup_root_stack():
+                pass
+            setup_root_stack = staticmethod(setup_root_stack)
+
+            push_root = None
+            pop_root = None
+
+            def __init__(self):
+                self.provide_current_frame = True
+                self.static_current = gcdata.static_root_start
+                self.static_roots_index = len(gcdata.static_roots)
+
+            def pop(self):
+                while self.static_current != gcdata.static_root_end:
+                    result = self.static_current
+                    self.static_current += sizeofaddr
+                    if result.address[0].address[0] != llmemory.NULL:
+                        return result.address[0]
+                i = self.static_roots_index
+                if i > 0:
+                    i -= 1
+                    self.static_roots_index = i
+                    return gcdata.static_roots[i]
+                if self.provide_current_frame:
+                    self.provide_current_frame = False
+                    frame = stack_unwind()
+                    return llmemory.cast_ptr_to_adr(frame)
+                return llmemory.NULL
+
+        return StackRootIterator
+
 # ___________________________________________________________________
 # calculate some statistics about the number of variables that need
 # to be cared for across a call

Modified: pypy/dist/pypy/rpython/module/ll_stack.py
==============================================================================
--- pypy/dist/pypy/rpython/module/ll_stack.py	(original)
+++ pypy/dist/pypy/rpython/module/ll_stack.py	Sat May 13 14:34:58 2006
@@ -5,7 +5,7 @@
 ll_stack_too_big.suggested_primitive = True
 
 def ll_stack_unwind():
-    rstack.stack_unwind()
+    return rstack.stack_unwind()
 ll_stack_unwind.suggested_primitive = True
 
 def ll_stack_check():

Modified: pypy/dist/pypy/rpython/rstack.py
==============================================================================
--- pypy/dist/pypy/rpython/rstack.py	(original)
+++ pypy/dist/pypy/rpython/rstack.py	Sat May 13 14:34:58 2006
@@ -6,7 +6,7 @@
 import inspect
 
 def stack_unwind():
-    pass
+    raise RuntimeError("cannot unwind stack in non-translated versions")
 
 def stack_frames_depth():
     return len(inspect.stack())

Modified: pypy/dist/pypy/translator/c/database.py
==============================================================================
--- pypy/dist/pypy/translator/c/database.py	(original)
+++ pypy/dist/pypy/translator/c/database.py	Sat May 13 14:34:58 2006
@@ -54,6 +54,8 @@
                     gcpolicy = gc.NoneGcPolicy
                 elif polname == 'framework':
                     gcpolicy = gc.FrameworkGcPolicy
+                elif polname == 'stacklessgc':
+                    gcpolicy = gc.StacklessFrameworkGcPolicy
                 else:
                     assert False, "unknown gc policy %r"%polname
             else:
@@ -198,7 +200,17 @@
         else:
             show_i = -1
         work_to_do = True
-        is_later_yet = False
+        transformations_to_finish = [self.gctransformer]
+        if self.stacklesstransformer:
+            transformations_to_finish.insert(0, self.stacklesstransformer)
+
+        def add_dependencies(newdependencies):
+            for value in newdependencies:
+                if isinstance(typeOf(value), ContainerType):
+                    self.getcontainernode(value)
+                else:
+                    self.get(value)
+        
         while work_to_do:
             while True:
                 if hasattr(self, 'pyobjmaker'):
@@ -211,36 +223,28 @@
                 if i == len(self.containerlist):
                     break
                 node = self.containerlist[i]
-                for value in node.enum_dependencies():
-                    if isinstance(typeOf(value), ContainerType):
-                        self.getcontainernode(value)
-                    else:
-                        self.get(value)
+                add_dependencies(node.enum_dependencies())
                 i += 1
                 self.completedcontainers = i
                 if i == show_i:
                     dump()
                     show_i += 1000
             work_to_do = False
-            if not is_later_yet:
-                newdependencies = self.gctransformer.finish() or []
-                if self.stacklesstransformer:
-                    newdependencies2 = self.stacklesstransformer.finish() or []
-                    newdependencies.extend(newdependencies2)
+
+            while transformations_to_finish:
+                transformation = transformations_to_finish.pop(0)
+                newdependencies = transformation.finish()
                 if newdependencies:
+                    add_dependencies(newdependencies)
+                    work_to_do = True
+                    break
+            else:
+                if self.latercontainerlist:
                     work_to_do = True
-                    for value in newdependencies:
-                        if isinstance(typeOf(value), ContainerType):
-                            self.getcontainernode(value)
-                        else:
-                            self.get(value)
-                is_later_yet = True
-            if self.latercontainerlist:
-                work_to_do = True
-                for node in self.latercontainerlist:
-                    node.make_funcgens()
-                    self.containerlist.append(node)
-                self.latercontainerlist = []
+                    for node in self.latercontainerlist:
+                        node.make_funcgens()
+                        self.containerlist.append(node)
+                    self.latercontainerlist = []
         self.completed = True
         if show_progress:
             dump()

Modified: pypy/dist/pypy/translator/c/gc.py
==============================================================================
--- pypy/dist/pypy/translator/c/gc.py	(original)
+++ pypy/dist/pypy/translator/c/gc.py	Sat May 13 14:34:58 2006
@@ -10,6 +10,7 @@
 PyObjPtr = Ptr(PyObject)
 
 class BasicGcPolicy(object):
+    requires_stackless = False
     
     def __init__(self, db, thread_enabled=False):
         self.db = db
@@ -391,3 +392,6 @@
         return 'OP_ZERO_MALLOC(%s, %s);' % (esize,
                                             eresult)
 
+class StacklessFrameworkGcPolicy(FrameworkGcPolicy):
+    transformerclass = gctransform.StacklessFrameworkGCTransformer
+    requires_stackless = True

Modified: pypy/dist/pypy/translator/c/genc.py
==============================================================================
--- pypy/dist/pypy/translator/c/genc.py	(original)
+++ pypy/dist/pypy/translator/c/genc.py	Sat May 13 14:34:58 2006
@@ -40,6 +40,9 @@
                               gcpolicy=self.gcpolicy, thread_enabled=self.thread_enabled)
 
         assert self.stackless in (False, 'old', True)
+        if self.gcpolicy.requires_stackless:
+            assert self.stackless != 'old'    # incompatible
+            self.stackless = True
         if self.stackless:
             if not self.standalone:
                 raise Exception("stackless: only for stand-alone builds")
@@ -50,7 +53,8 @@
                 from pypy.translator.stackless.transform import \
                                                        StacklessTransformer
                 db.stacklesstransformer = StacklessTransformer(translator,
-                                                       self.originalentrypoint)
+                                              self.originalentrypoint,
+                                              self.gcpolicy.requires_stackless)
                 self.entrypoint = db.stacklesstransformer.slp_entry_point
 
         # pass extra options into pyobjmaker

Modified: pypy/dist/pypy/translator/c/test/test_newgc.py
==============================================================================
--- pypy/dist/pypy/translator/c/test/test_newgc.py	(original)
+++ pypy/dist/pypy/translator/c/test/test_newgc.py	Sat May 13 14:34:58 2006
@@ -318,8 +318,10 @@
     def test_empty_collect(self):
         def f():
             llop.gc__collect(lltype.Void)
+            return 41
         fn = self.getcompiled(f)
-        fn()
+        res = fn()
+        assert res == 41
 
     def test_framework_simple(self):
         def g(x): # cannot cause a collect
@@ -529,3 +531,18 @@
         fn = self.getcompiled(f)
         res = fn()
         assert res == -70
+
+class TestUsingStacklessFramework(TestUsingFramework):
+    from pypy.translator.c.gc import StacklessFrameworkGcPolicy as gcpolicy
+
+    def getcompiled(self, f):
+        py.test.skip('in-progress')
+        # XXX quick hack
+        from pypy.translator.c.test.test_stackless import StacklessTest
+        runner = StacklessTest()
+        runner.gcpolicy = self.gcpolicy
+        runner.stacklessmode = True
+        res = runner.wrap_stackless_function(f)
+        def compiled():
+            return res
+        return compiled

Modified: pypy/dist/pypy/translator/stackless/code.py
==============================================================================
--- pypy/dist/pypy/translator/stackless/code.py	(original)
+++ pypy/dist/pypy/translator/stackless/code.py	Sat May 13 14:34:58 2006
@@ -128,6 +128,7 @@
         # STATE 0: now the stack is unwound, and we can count the frames
         # in the heap
         cur = global_state.top
+        global_state.top = frame.null_state
         global_state.restart_substate = -1
         depth = 0
         while cur:
@@ -153,7 +154,13 @@
     else:
         # STATE 0: now the stack is unwound.  That was the goal.
         # Return to caller.
+        cur = global_state.top
+        global_state.top = frame.null_state
         global_state.restart_substate = -1
+        # Pass the caller's own saved state back to it.
+        # The StacklessFrameworkGCTransformer uses this for introspection.
+        return lltype.cast_opaque_ptr(frame.OPAQUE_STATE_HEADER_PTR,
+                                      cur.f_back)
 ll_stack_unwind.stackless_explicit = True
 
 INDEX_UNWIND = frame.RestartInfo.add_prebuilt(ll_stack_unwind,

Modified: pypy/dist/pypy/translator/stackless/test/test_depth.py
==============================================================================
--- pypy/dist/pypy/translator/stackless/test/test_depth.py	(original)
+++ pypy/dist/pypy/translator/stackless/test/test_depth.py	Sat May 13 14:34:58 2006
@@ -87,3 +87,11 @@
 
     res = run_stackless_function(fn)
     assert res == 15
+
+def test_stack_unwind_retval():
+    def fn():
+        frame = rstack.stack_unwind()
+        return int(bool(frame))
+
+    res = llinterp_stackless_function(fn)
+    assert res == 1

Modified: pypy/dist/pypy/translator/stackless/transform.py
==============================================================================
--- pypy/dist/pypy/translator/stackless/transform.py	(original)
+++ pypy/dist/pypy/translator/stackless/transform.py	Sat May 13 14:34:58 2006
@@ -91,12 +91,14 @@
         return T, fieldnames
 
 class StacklessAnalyzer(graphanalyze.GraphAnalyzer):
-    def __init__(self, translator, unwindtype):
+    def __init__(self, translator, unwindtype, stackless_gc):
         graphanalyze.GraphAnalyzer.__init__(self, translator)
         self.unwindtype = unwindtype
+        self.stackless_gc = stackless_gc
 
     def operation_is_true(self, op):
-        return op.opname == 'yield_current_frame_to_caller'
+        return (op.opname == 'yield_current_frame_to_caller' or
+                op.opname.startswith('malloc') and self.stackless_gc)
 
     def analyze_link(self, graph, link):
         if link.target is graph.exceptblock:
@@ -116,7 +118,8 @@
                             
 
 class StacklessTransformer(object):
-    def __init__(self, translator, entrypoint):
+
+    def __init__(self, translator, entrypoint, stackless_gc=False):
         self.translator = translator
 
         self.frametyper = FrameTyper()
@@ -129,7 +132,8 @@
             self.translator.rtyper,
             bk.getuniqueclassdef(code.UnwindException)).lowleveltype
         self.analyzer = StacklessAnalyzer(translator,
-                                          self.unwind_exception_type)
+                                          self.unwind_exception_type,
+                                          stackless_gc)
 
         # the point of this little dance is to not annotate
         # code.global_state.masterarray as a constant.
@@ -191,7 +195,7 @@
                     code.ll_frame_clone, [s_StatePtr], s_StatePtr),
             ll_stack.ll_stack_unwind:
                 mixlevelannotator.constfunc(
-                    code.ll_stack_unwind, [], annmodel.s_None),
+                    code.ll_stack_unwind, [], s_StatePtr),
             }
         self.yield_current_frame_to_caller_ptr = mixlevelannotator.constfunc(
             code.yield_current_frame_to_caller, [], s_StatePtr)
@@ -386,7 +390,8 @@
             if op.opname == 'yield_current_frame_to_caller':
                 op = replace_with_call(self.yield_current_frame_to_caller_ptr)
 
-            if op.opname in ('direct_call', 'indirect_call'):
+            if (op.opname in ('direct_call', 'indirect_call') or
+                op.opname.startswith('malloc')):
                 # trap calls to stackless-related suggested primitives
                 if op.opname == 'direct_call':
                     func = getattr(op.args[0].value._obj, '_callable', None)


From antocuni at codespeak.net  Sat May 13 15:04:16 2006
From: antocuni at codespeak.net (antocuni at codespeak.net)
Date: Sat, 13 May 2006 15:04:16 +0200 (CEST)
Subject: [pypy-svn] r27169 - in pypy/dist/pypy: annotation
	rpython/ootypesystem/test
Message-ID: <20060513130416.28EE5100A9@code0.codespeak.net>

Author: antocuni
Date: Sat May 13 15:04:05 2006
New Revision: 27169

Modified:
   pypy/dist/pypy/annotation/builtin.py
   pypy/dist/pypy/rpython/ootypesystem/test/test_ooann.py
   pypy/dist/pypy/rpython/ootypesystem/test/test_oortype.py
Log:
Made the annotator aware that oostring is a builtin function. This
fixed some failing tests in test_ooann, test_oortype, test_rstr.



Modified: pypy/dist/pypy/annotation/builtin.py
==============================================================================
--- pypy/dist/pypy/annotation/builtin.py	(original)
+++ pypy/dist/pypy/annotation/builtin.py	Sat May 13 15:04:05 2006
@@ -501,6 +501,10 @@
     assert isinstance(i, SomeOOInstance)
     return SomeInteger()
 
+def oostring(obj):
+    assert isinstance(obj, (SomeInteger, SomeChar, SomeString))
+    return SomeString()
+
 BUILTIN_ANALYZERS[ootype.instanceof] = instanceof
 BUILTIN_ANALYZERS[ootype.new] = new
 BUILTIN_ANALYZERS[ootype.null] = null
@@ -508,6 +512,7 @@
 BUILTIN_ANALYZERS[ootype.classof] = classof
 BUILTIN_ANALYZERS[ootype.subclassof] = subclassof
 BUILTIN_ANALYZERS[ootype.ooidentityhash] = ooidentityhash
+BUILTIN_ANALYZERS[ootype.oostring] = oostring
 
 #________________________________
 # non-gc objects

Modified: pypy/dist/pypy/rpython/ootypesystem/test/test_ooann.py
==============================================================================
--- pypy/dist/pypy/rpython/ootypesystem/test/test_ooann.py	(original)
+++ pypy/dist/pypy/rpython/ootypesystem/test/test_ooann.py	Sat May 13 15:04:05 2006
@@ -206,3 +206,12 @@
     a = RPythonAnnotator()
     s = a.build_types(oof, [])
     assert s == annmodel.SomeOOInstance(String)
+
+def test_oostring():
+    def oof():
+        return new
+
+    a = RPythonAnnotator()
+    s = a.build_types(oof, [])
+    assert isinstance(s, annmodel.SomeBuiltin)
+

Modified: pypy/dist/pypy/rpython/ootypesystem/test/test_oortype.py
==============================================================================
--- pypy/dist/pypy/rpython/ootypesystem/test/test_oortype.py	(original)
+++ pypy/dist/pypy/rpython/ootypesystem/test/test_oortype.py	Sat May 13 15:04:05 2006
@@ -202,3 +202,4 @@
 
     ch = 'a'
     res = interpret(oof, [ch], type_system='ootype')
+    assert res._str == 'a'


From stephan at codespeak.net  Sat May 13 15:20:48 2006
From: stephan at codespeak.net (stephan at codespeak.net)
Date: Sat, 13 May 2006 15:20:48 +0200 (CEST)
Subject: [pypy-svn] r27170 - pypy/dist/pypy/module/stackless/test
Message-ID: <20060513132048.44EA0100AA@code0.codespeak.net>

Author: stephan
Date: Sat May 13 15:20:46 2006
New Revision: 27170

Modified:
   pypy/dist/pypy/module/stackless/test/stackless_.py
Log:
added (empty) remaining interface for stackless including doc strings.
There is no added functionality yet.


Modified: pypy/dist/pypy/module/stackless/test/stackless_.py
==============================================================================
--- pypy/dist/pypy/module/stackless/test/stackless_.py	(original)
+++ pypy/dist/pypy/module/stackless/test/stackless_.py	Sat May 13 15:20:46 2006
@@ -1,7 +1,174 @@
+"""
+The Stackless module allows you to do multitasking without using threads.
+The essential objects are tasklets and channels.
+Please refer to their documentation.
+"""
+
 from stackless import coroutine
 
 __all__ = 'run getcurrent getmain schedule tasklet channel'.split()
 
+# interface from original stackless
+# class attributes are placeholders for some kind of descriptor
+# (to be filled in later).
+
+class bomb(object):
+    """
+    A bomb object is used to hold exceptions in tasklets.
+    Whenever a tasklet is activated and its tempval is a bomb,
+    it will explode as an exception.
+    
+    You can create a bomb by hand and attach it to a tasklet if you like.
+    Note that bombs are 'sloppy' about the argument list, which means that
+    the following works, although you should use '*sys.exc_info()'.
+    
+    from stackless import *; import sys
+    t = tasklet(lambda:42)()
+    try: 1/0
+    except: b = bomb(sys.exc_info())
+    
+    t.tempval = b
+    nt.run()  # let the bomb explode
+    """
+
+    traceback = None
+    type = None
+    value = None
+
+class cframe(object):
+    """
+    """
+    __slots__ = ['f_back','obj1','obj2','obj3','i','n']
+
+# channel: see below
+
+class cstack(object):
+    """
+    A CStack object serves to save the stack slice which is involved
+    during a recursive Python call. It will also be used for pickling
+    of program state. This structure is highly platform dependant.
+    Note: For inspection, str() can dump it as a string.
+    """
+
+def enable_softswitch(flag):
+    """
+    enable_softswitch(flag) -- control the switching behavior.
+    Tasklets can be either switched by moving C stack slices around
+    or by avoiding stack changes at all. The latter is only possible
+    in the top interpreter level. Switching it off is for timing and
+    debugging purposes. This flag exists once for the whole process.
+    For inquiry only, use the phrase
+    ret = enable_softswitch(0); enable_softswitch(ret)
+    By default, soft switching is enabled.
+    """
+    pass
+
+def get_thread_info(thread_id):
+    """
+    get_thread_info(thread_id) -- return a 3-tuple of the thread's
+    main tasklet, current tasklet and runcount.
+    To obtain a list of all thread infos, use
+    
+    map (stackless.get_thread_info, stackless.threads)
+    """
+    pass
+
+# def getcurrent() : see below
+
+# def run(timeout): see below
+
+# def schedule(retval=stackless.current) : see below
+
+def schedule_remove(retval=None):
+    """
+    schedule(retval=stackless.current) -- switch to the next runnable tasklet.
+    The return value for this call is retval, with the current
+    tasklet as default.
+    schedule_remove(retval=stackless.current) -- ditto, and remove self.
+    """
+    pass
+
+def set_channel_callback(callable):
+    """
+    set_channel_callback(callable) -- install a callback for channels.
+    Every send/receive action will call the callback function.
+    Example:
+    def channel_cb(channel, tasklet, sending, willblock):
+        ...
+    sending and willblock are integers.
+    Pass None to switch monitoring off again.
+    """
+    pass
+
+def set_schedule_callback(callable):
+    """
+    set_schedule_callback(callable) -- install a callback for scheduling.
+    Every explicit or implicit schedule will call the callback function.
+    Example:
+    def schedule_cb(prev, next):
+        ...
+    When a tasklet is dying, next is None.
+    When main starts up or after death, prev is None.
+    Pass None to switch monitoring off again.
+    """
+    pass
+
+class slpmodule(object):
+    """
+    The stackless module has a special type derived from
+    the module type, in order to be able to override some attributes.
+    __tasklet__ and __channel__ are the default types
+    to be used when these objects must be instantiated internally.
+    runcount, current and main are attribute-like short-hands
+    for the getruncount, getcurrent and getmain module functions.
+    """
+
+# class tasklet: see below
+
+def test_cframe(switches, words=0):
+    """
+    test_cframe(switches, words=0) -- a builtin testing function that does 
+    nothing but tasklet switching. The function will call 
+    PyStackless_Schedule() for switches times and then finish.
+    If words is given, as many words will be allocated on the C stack.
+    Usage: Create two tasklets for test_cframe and run them by run().
+    
+        t1 = tasklet(test_cframe)(500000)
+        t2 = tasklet(test_cframe)(500000)
+        run()
+    This can be used to measure the execution time of 1.000.000 switches.
+    """
+    pass
+
+def test_cframe_nr(switches):
+    """
+    test_cframe_nr(switches) -- a builtin testing function that does nothing
+    but soft tasklet switching. The function will call 
+    PyStackless_Schedule_nr() for switches times and then finish.
+    Usage: Cf. test_cframe().
+    """
+    pass
+
+def test_outside():
+    """
+    test_outside() -- a builtin testing function.
+    This function simulates an application that does not run "inside"
+    Stackless, with active, running frames, but always needs to initialize
+    the main tasklet to get "\xednside".
+    The function will terminate when no other tasklets are runnable.
+    
+    Typical usage: Create a tasklet for test_cframe and run by test_outside().
+    
+        t1 = tasklet(test_cframe)(1000000)
+        test_outside()
+
+    This can be used to measure the execution time of 1.000.000 switches.
+    """
+    pass
+
+
+# end interface
+
 main_tasklet = None
 next_tasklet = None
 scheduler = None
@@ -16,9 +183,23 @@
     coro_reg[c] = mt
 
 def run():
+    """
+    run_watchdog(timeout) -- run tasklets until they are all
+    done, or timeout instructions have passed. Tasklets must
+    provide cooperative schedule() calls.
+    If the timeout is met, the function returns.
+    The calling tasklet is put aside while the tasklets are running.
+    It is inserted back after the function stops, right before the
+    tasklet that caused a timeout, if any.
+    If an exception occours, it will be passed to the main tasklet.
+    """
     schedule()
 
 def getcurrent():
+    """
+    getcurrent() -- return the currently executing tasklet.
+    """
+
     c = coroutine.getcurrent()
     return coro_reg[c]
 
@@ -26,9 +207,26 @@
     return main_tasklet
 
 def schedule():
+    """
+    schedule(retval=stackless.current) -- switch to the next runnable tasklet.
+    The return value for this call is retval, with the current
+    tasklet as default.
+    schedule_remove(retval=stackless.current) -- ditto, and remove self.
+    """
     scheduler.schedule()
 
 class tasklet(object):
+    """
+    A tasklet object represents a tiny task in a Python thread.
+    At program start, there is always one running main tasklet.
+    New tasklets can be created with methods from the stackless
+    module.
+    """
+#    __slots__ = ['alive','atomic','block_trap','blocked','frame',
+#                 'ignore_nesting','is_current','is_main',
+#                 'nesting_level','next','paused','prev','recursion_depth',
+#                 'restorable','scheduled','thread_id']
+
     def __init__(self,func=None):
         self._func = func
 
@@ -39,39 +237,167 @@
         self.insert()
         return self
 
-    def awake(self):pass
+    def become(self, retval=None):
+        """
+        t.become(retval) -- catch the current running frame in a tasklet.
+        It is also inserted at the end of the runnables chain.
+        If it is a toplevel frame (and therefore has no caller), an exception 
+        is raised.  The function result is the tasklet itself. retval is 
+        passed to the calling frame.
+        If retval is not given, the tasklet is used as default.
+        """
+        pass
+
+    def bind(self):
+        """
+        Binding a tasklet to a callable object.
+        The callable is usually passed in to the constructor.
+        In some cases, it makes sense to be able to re-bind a tasklet,
+        after it has been run, in order to keep its identity.
+        Note that a tasklet can only be bound when it doesn't have a frame.
+        """
+        pass
+
+    def capture(self, retval=None):
+        """
+        t.capture(retval) -- capture the current running frame in a tasklet,
+        like t.become(). In addition the tasklet is run immediately, and the
+        parent tasklet is removed from the runnables and returned as the value.
+        """
+        pass
 
-    def sleep(self):pass
-
-    def run(self):
-        scheduler.setnexttask(self)
-        schedule()
+    cstate = None
 
     def insert(self):
+        """
+        Insert this tasklet at the end of the scheduler list,
+        given that it isn't blocked.
+        Blocked tasklets need to be reactivated by channels.
+        """
         scheduler.insert(self)
 
+    def kill(self):
+        """
+        tasklet.kill -- raise a TaskletExit exception for the tasklet.
+        Note that this is a regular exception that can be caught.
+        The tasklet is immediately activated.
+        If the exception passes the toplevel frame of the tasklet,
+        the tasklet will silently die.
+        """
+        pass
+
+    def raise_exception(self, exc, value):
+        """
+        tasklet.raise_exception(exc, value) -- raise an exception for the 
+        tasklet.  exc must be a subclass of Exception.
+        The tasklet is immediately activated.
+        """
+        pass
+
     def remove(self):
+        """
+        Removing a tasklet from the runnables queue.
+        Note: If this tasklet has a non-trivial C stack attached,
+        it will be destructed when the containing thread state is destroyed.
+        Since this will happen in some unpredictable order, it may cause 
+        unwanted side-effects. Therefore it is recommended to either run 
+        tasklets to the end or to explicitly kill() them.
+        """
         scheduler.remove(self)
 
-    def kill(self):pass
+    def run(self):
+        """
+        Run this tasklet, given that it isn't blocked.
+        Blocked tasks need to be reactivated by channels.
+        """
+        scheduler.setnexttask(self)
+        schedule()
+
+    def set_atomic(self):
+        """
+        t.set_atomic(flag) -- set tasklet atomic status and return current one.
+        If set, the tasklet will not be auto-scheduled.
+        This flag is useful for critical sections which should not be 
+        interrupted.
+        usage:
+            tmp = t.set_atomic(1)
+            # do critical stuff
+            t.set_atomic(tmp)
+        Note: Whenever a new tasklet is created, the atomic flag is initialized
+        with the atomic flag of the current tasklet.Atomic behavior is 
+        additionally influenced by the interpreter nesting level.
+        See set_ignore_nesting.
+        """
+        pass
+
+    def set_ignore_nesting(self,flag):
+        """
+        t.set_ignore_nesting(flag) -- set tasklet ignore_nesting status and 
+        return current one. If set, the tasklet may be be auto-scheduled, 
+        even if its nesting_level is > 0.
+        This flag makes sense if you know that nested interpreter levels are 
+        safe for auto-scheduling. This is on your own risk, handle with care!
+        usage:
+            tmp = t.set_ignore_nesting(1)
+            # do critical stuff
+            t.set_ignore_nesting(tmp)
+        """
+        pass
+
+    def setup(self,*argl,**argd):
+        """
+        supply the parameters for the callable
+        """
+        pass
+
+    tempval = None
 
 class channel(object):
+    """
+    A channel object is used for communication between tasklets.
+    By sending on a channel, a tasklet that is waiting to receive
+    is resumed. If there is no waiting receiver, the sender is suspended.
+    By receiving from a channel, a tasklet that is waiting to send
+    is resumed. If there is no waiting sender, the receiver is suspended.
+    """
+
+#    __slots__ = ['balance','closed','closing','preference','queue',
+#                 'schedule_all']
+
     def __init__(self):
         self.balance = 0
         self._readq = []
         self._writeq = []
 
-    def send(self, msg):
-        ct = getcurrent()
-        scheduler.remove(ct)
-        self._writeq.append((ct,msg))
-        self.balance += 1
-        if self._readq:
-            nt, self._readq = self._readq[0], self._readq[1:]
-            scheduler.priorityinsert(nt)
-        schedule()
+    def close(self):
+        """
+        channel.close() -- stops the channel from enlarging its queue.
+        
+        If the channel is not empty, the flag 'closing' becomes true.
+        If the channel is empty, the flag 'closed' becomes true.
+        """
+        pass
+
+    def next(self):
+        """
+        x.next() -> the next value, or raise StopIteration
+        """
+        pass
+
+    def open(self):
+        """
+        channel.open() -- reopen a channel. See channel.close.
+        """
 
     def receive(self):
+        """
+        channel.receive() -- receive a value over the channel.
+        If no other tasklet is already sending on the channel,
+        the receiver will be blocked. Otherwise, the receiver will
+        continue immediately, and the sender is put at the end of
+        the runnables list.
+        The above policy can be changed by setting channel flags.
+        """
         ct = getcurrent()
         if self._writeq:
             (wt,retval), self._writeq = self._writeq[0], self._writeq[1:]
@@ -84,6 +410,42 @@
             schedule()
             return self.receive()
 
+    def send(self, msg):
+        """
+        channel.send(value) -- send a value over the channel.
+        If no other tasklet is already receiving on the channel,
+        the sender will be blocked. Otherwise, the receiver will
+        be activated immediately, and the sender is put at the end of
+        the runnables list.
+        """
+        ct = getcurrent()
+        scheduler.remove(ct)
+        self._writeq.append((ct,msg))
+        self.balance += 1
+        if self._readq:
+            nt, self._readq = self._readq[0], self._readq[1:]
+            scheduler.priorityinsert(nt)
+        schedule()
+
+    def send_exception(self, exc, value):
+        """
+        channel.send_exception(exc, value) -- send an exception over the 
+        channel. exc must be a subclass of Exception.
+        Behavior is like channel.send, but that the receiver gets an exception.
+        """
+        pass
+
+    def send_sequence(self, value):
+        """
+        channel.send(value) -- send a value over the channel.
+        If no other tasklet is already receiving on the channel,
+        the sender will be blocked. Otherwise, the receiver will
+        be activated immediately, and the sender is put at the end of
+        the runnables list.
+        """
+        pass
+
+
 class Scheduler(object):
     def __init__(self):
         self.tasklist = []


From antocuni at codespeak.net  Sat May 13 15:39:29 2006
From: antocuni at codespeak.net (antocuni at codespeak.net)
Date: Sat, 13 May 2006 15:39:29 +0200 (CEST)
Subject: [pypy-svn] r27171 - in pypy/dist/pypy: annotation
	rpython/ootypesystem/test
Message-ID: <20060513133929.1BEFB100AA@code0.codespeak.net>

Author: antocuni
Date: Sat May 13 15:39:18 2006
New Revision: 27171

Modified:
   pypy/dist/pypy/annotation/builtin.py
   pypy/dist/pypy/rpython/ootypesystem/test/test_ooann.py
Log:
Corrected a bug in the annotation of oostring, and a typo in
test_ooann (thanks to pedronis).



Modified: pypy/dist/pypy/annotation/builtin.py
==============================================================================
--- pypy/dist/pypy/annotation/builtin.py	(original)
+++ pypy/dist/pypy/annotation/builtin.py	Sat May 13 15:39:18 2006
@@ -502,8 +502,9 @@
     return SomeInteger()
 
 def oostring(obj):
-    assert isinstance(obj, (SomeInteger, SomeChar, SomeString))
-    return SomeString()
+    assert (isinstance(obj, (SomeInteger, SomeChar)) or
+            isinstance(obj, SomeOOInstance) and obj.ootype is ootype.String)
+    return SomeOOInstance(ootype.String)
 
 BUILTIN_ANALYZERS[ootype.instanceof] = instanceof
 BUILTIN_ANALYZERS[ootype.new] = new

Modified: pypy/dist/pypy/rpython/ootypesystem/test/test_ooann.py
==============================================================================
--- pypy/dist/pypy/rpython/ootypesystem/test/test_ooann.py	(original)
+++ pypy/dist/pypy/rpython/ootypesystem/test/test_ooann.py	Sat May 13 15:39:18 2006
@@ -209,7 +209,7 @@
 
 def test_oostring():
     def oof():
-        return new
+        return oostring
 
     a = RPythonAnnotator()
     s = a.build_types(oof, [])


From mwh at codespeak.net  Sat May 13 16:18:21 2006
From: mwh at codespeak.net (mwh at codespeak.net)
Date: Sat, 13 May 2006 16:18:21 +0200 (CEST)
Subject: [pypy-svn] r27173 - pypy/extradoc/sprintinfo/ddorf2006
Message-ID: <20060513141821.D3F0D100AA@code0.codespeak.net>

Author: mwh
Date: Sat May 13 16:18:20 2006
New Revision: 27173

Added:
   pypy/extradoc/sprintinfo/ddorf2006/
   pypy/extradoc/sprintinfo/ddorf2006/announce.txt   (contents, props changed)
   pypy/extradoc/sprintinfo/ddorf2006/people.txt   (contents, props changed)
Log:
initial ddorf sprint announcement/people.txt


Added: pypy/extradoc/sprintinfo/ddorf2006/announce.txt
==============================================================================
--- (empty file)
+++ pypy/extradoc/sprintinfo/ddorf2006/announce.txt	Sat May 13 16:18:20 2006
@@ -0,0 +1,28 @@
+Duesseldorf internal-ish sprint 2-9 June 2006
+====================================================
+
+The next PyPy sprint will be held in the Computer Science department of
+Heinrich-Heine Universitaet Duesseldorf from the 2nd to the 9th of June.
+
+The main focus of the sprint will be on the goals of the upcoming June 0.9
+release:
+
+* The extension module compiler.  The goal is to be able to use a single
+  RPython source code as an extension module for both PyPy and CPython.
+  The means to get there is -- most likely -- by compiling ctypes-based
+  modules into either pypy-c or a CPython dll/so.
+
+* Write some more modules in this style with ctypes.
+
+* Stackless: the big missing feature is pickling running tasklets.
+  There is also some smaller work that needs to be done, like exposing
+  all the existing RPython-level interfaces to app-level
+  (e.g. greenlets).
+
+* Write more documentation.
+
+* Misc topics, depending on interests: back-ends (CLI, Squeak), testing
+  framework, modified semantics (security/sandboxing...), etc.
+
+
+.. _`pypy-sprint mailing list`: http://codespeak.net/mailman/listinfo/pypy-sprint

Added: pypy/extradoc/sprintinfo/ddorf2006/people.txt
==============================================================================
--- (empty file)
+++ pypy/extradoc/sprintinfo/ddorf2006/people.txt	Sat May 13 16:18:20 2006
@@ -0,0 +1,41 @@
+People coming to the Duesseldorf sprint June 2006
+==================================================
+
+People who have a ``?`` in their arrive/depart or accomodation
+column are known to be coming but there are no details 
+available yet from them.
+
+==================== ============== =====================
+    Name              Arrive/Depart     Accomodation 
+==================== ============== =====================
+Michael Hudson       ?              private
+Armin Rigo           ?              private
+==================== ============== =====================
+
+People on the following list were present at previous sprints: 
+
+==================== ============== =====================
+       Name          Arrive/Depart  Accomodation 
+==================== ============== =====================
+Anders Chrigstroem   ?              ?
+Holger Krekel        ?              ?
+Samuele Pedroni      ?              ?
+Christian Tismer     ?              ?
+Anders Lehmann       ?              ?
+Jacob Hallen         ?              ?
+Niklaus Haldimann    ?              ?
+Aurelien Campeas     ?              ?
+Alexandre Fayolle    ?              ?
+Lene Wagner          ?              ?
+Amaury Forgeot d'Arc ?              ?
+Valentino Volonghi   ?              ?
+Boris Feigin	     ?              ?
+Andrew Thompson      ?              ?
+Bert Freudenberg     ?              ?
+Laura Creighton      ?              ?
+Beatrice Duering     ?              ?
+Eric van Riet Paap   ?              ?
+Carl Friedrich Bolz  ?              ?
+Richard Emslie       ?              ?
+Johan Hahn           ?              ?
+==================== ============== =====================


From hpk at codespeak.net  Sat May 13 16:21:29 2006
From: hpk at codespeak.net (hpk at codespeak.net)
Date: Sat, 13 May 2006 16:21:29 +0200 (CEST)
Subject: [pypy-svn] r27174 - pypy/extradoc/sprintinfo/ddorf2006
Message-ID: <20060513142129.63471100B4@code0.codespeak.net>

Author: hpk
Date: Sat May 13 16:21:27 2006
New Revision: 27174

Modified:
   pypy/extradoc/sprintinfo/ddorf2006/people.txt
Log:
adding myself 



Modified: pypy/extradoc/sprintinfo/ddorf2006/people.txt
==============================================================================
--- pypy/extradoc/sprintinfo/ddorf2006/people.txt	(original)
+++ pypy/extradoc/sprintinfo/ddorf2006/people.txt	Sat May 13 16:21:27 2006
@@ -10,6 +10,7 @@
 ==================== ============== =====================
 Michael Hudson       ?              private
 Armin Rigo           ?              private
+Holger Krekel        2nd-9th        ?
 ==================== ============== =====================
 
 People on the following list were present at previous sprints: 
@@ -18,7 +19,6 @@
        Name          Arrive/Depart  Accomodation 
 ==================== ============== =====================
 Anders Chrigstroem   ?              ?
-Holger Krekel        ?              ?
 Samuele Pedroni      ?              ?
 Christian Tismer     ?              ?
 Anders Lehmann       ?              ?


From hpk at codespeak.net  Sat May 13 16:26:50 2006
From: hpk at codespeak.net (hpk at codespeak.net)
Date: Sat, 13 May 2006 16:26:50 +0200 (CEST)
Subject: [pypy-svn] r27175 - pypy/extradoc/sprintinfo/ddorf2006
Message-ID: <20060513142650.AAE66100B2@code0.codespeak.net>

Author: hpk
Date: Sat May 13 16:26:48 2006
New Revision: 27175

Modified:
   pypy/extradoc/sprintinfo/ddorf2006/announce.txt
Log:
just a quick amending of the announcement (need to leave for now) 



Modified: pypy/extradoc/sprintinfo/ddorf2006/announce.txt
==============================================================================
--- pypy/extradoc/sprintinfo/ddorf2006/announce.txt	(original)
+++ pypy/extradoc/sprintinfo/ddorf2006/announce.txt	Sat May 13 16:26:48 2006
@@ -1,4 +1,4 @@
-Duesseldorf internal-ish sprint 2-9 June 2006
+Duesseldorf PyPy sprint 2-9 June 2006
 ====================================================
 
 The next PyPy sprint will be held in the Computer Science department of
@@ -24,5 +24,11 @@
 * Misc topics, depending on interests: back-ends (CLI, Squeak), testing
   framework, modified semantics (security/sandboxing...), etc.
 
+If you'd like to come, please subscribe to the `pypy-sprint mailing list`_
+and drop a note about your interests and post any questions.  More 
+(organisational) information will be send to that list.  We'll keep
+a list of `people`_ which we'll update (or you can do so yourself
+if you codespeak commit rights). 
 
 .. _`pypy-sprint mailing list`: http://codespeak.net/mailman/listinfo/pypy-sprint
+.. _`people`: http://codespeak.net/pypy/extradoc/sprintinfo/ddorf2006/people.html


From pedronis at codespeak.net  Sat May 13 16:34:30 2006
From: pedronis at codespeak.net (pedronis at codespeak.net)
Date: Sat, 13 May 2006 16:34:30 +0200 (CEST)
Subject: [pypy-svn] r27176 - pypy/dist/pypy/translator/backendopt
Message-ID: <20060513143430.DCDFE100AA@code0.codespeak.net>

Author: pedronis
Date: Sat May 13 16:34:29 2006
New Revision: 27176

Modified:
   pypy/dist/pypy/translator/backendopt/all.py
Log:
disable propagate again



Modified: pypy/dist/pypy/translator/backendopt/all.py
==============================================================================
--- pypy/dist/pypy/translator/backendopt/all.py	(original)
+++ pypy/dist/pypy/translator/backendopt/all.py	Sat May 13 16:34:29 2006
@@ -16,7 +16,7 @@
                                       inline_threshold=1,
                                       mallocs=True,
                                       merge_if_blocks_to_switch=True,
-                                      propagate=True,
+                                      propagate=False,
                                       heap2stack=False,
                                       clever_malloc_removal=False):
 


From pedronis at codespeak.net  Sat May 13 16:37:13 2006
From: pedronis at codespeak.net (pedronis at codespeak.net)
Date: Sat, 13 May 2006 16:37:13 +0200 (CEST)
Subject: [pypy-svn] r27177 - pypy/dist/pypy/translator/c
Message-ID: <20060513143713.46D1E100AA@code0.codespeak.net>

Author: pedronis
Date: Sat May 13 16:37:12 2006
New Revision: 27177

Modified:
   pypy/dist/pypy/translator/c/genc.py
Log:
this code requires the gcpolicy instance!



Modified: pypy/dist/pypy/translator/c/genc.py
==============================================================================
--- pypy/dist/pypy/translator/c/genc.py	(original)
+++ pypy/dist/pypy/translator/c/genc.py	Sat May 13 16:37:12 2006
@@ -40,7 +40,7 @@
                               gcpolicy=self.gcpolicy, thread_enabled=self.thread_enabled)
 
         assert self.stackless in (False, 'old', True)
-        if self.gcpolicy.requires_stackless:
+        if db.gcpolicy.requires_stackless:
             assert self.stackless != 'old'    # incompatible
             self.stackless = True
         if self.stackless:
@@ -54,7 +54,7 @@
                                                        StacklessTransformer
                 db.stacklesstransformer = StacklessTransformer(translator,
                                               self.originalentrypoint,
-                                              self.gcpolicy.requires_stackless)
+                                              db.gcpolicy.requires_stackless)
                 self.entrypoint = db.stacklesstransformer.slp_entry_point
 
         # pass extra options into pyobjmaker


From tismer at codespeak.net  Sat May 13 16:42:31 2006
From: tismer at codespeak.net (tismer at codespeak.net)
Date: Sat, 13 May 2006 16:42:31 +0200 (CEST)
Subject: [pypy-svn] r27178 - pypy/dist/pypy/module/stackless/test
Message-ID: <20060513144231.7C7F1100AA@code0.codespeak.net>

Author: tismer
Date: Sat May 13 16:42:30 2006
New Revision: 27178

Modified:
   pypy/dist/pypy/module/stackless/test/stackless_.py
Log:
some hints, comments and clarifications about how to implement stackless and what to ignore

Modified: pypy/dist/pypy/module/stackless/test/stackless_.py
==============================================================================
--- pypy/dist/pypy/module/stackless/test/stackless_.py	(original)
+++ pypy/dist/pypy/module/stackless/test/stackless_.py	Sat May 13 16:42:30 2006
@@ -11,7 +11,14 @@
 # interface from original stackless
 # class attributes are placeholders for some kind of descriptor
 # (to be filled in later).
-
+
+note = """
+The bomb object decouples exception creation and exception
+raising. This is necessary to support channels which don't
+immediately react on messages.
+
+This is a necessary Stackless 3.1 feature.
+"""
 class bomb(object):
     """
     A bomb object is used to hold exceptions in tasklets.
@@ -34,14 +41,24 @@
     traceback = None
     type = None
     value = None
-
+
+note = """
+cframes are an implementation detail.
+Do not implement this now. If we need such a thing in PyPy,
+then it will probably have a different layout.
+"""
 class cframe(object):
     """
     """
     __slots__ = ['f_back','obj1','obj2','obj3','i','n']
 
 # channel: see below
-
+
+note = """
+The future of C stacks is undecided, yet. This applies
+for Stackless, only at the moment. PyPy will use soft-switching
+only, until we support external callbacks.
+"""
 class cstack(object):
     """
     A CStack object serves to save the stack slice which is involved
@@ -49,7 +66,11 @@
     of program state. This structure is highly platform dependant.
     Note: For inspection, str() can dump it as a string.
     """
-
+
+note = """
+I would implement it as a simple flag but let it issue
+a warning that it has no effect.
+"""
 def enable_softswitch(flag):
     """
     enable_softswitch(flag) -- control the switching behavior.
@@ -62,7 +83,10 @@
     By default, soft switching is enabled.
     """
     pass
-
+
+note = """
+Implementation can be deferred.
+"""
 def get_thread_info(thread_id):
     """
     get_thread_info(thread_id) -- return a 3-tuple of the thread's
@@ -78,7 +102,8 @@
 # def run(timeout): see below
 
 # def schedule(retval=stackless.current) : see below
-
+
+note = 'needed'
 def schedule_remove(retval=None):
     """
     schedule(retval=stackless.current) -- switch to the next runnable tasklet.
@@ -87,7 +112,10 @@
     schedule_remove(retval=stackless.current) -- ditto, and remove self.
     """
     pass
-
+
+note = """
+should be implemented for debugging purposes. Low priority
+"""
 def set_channel_callback(callable):
     """
     set_channel_callback(callable) -- install a callback for channels.
@@ -100,6 +128,9 @@
     """
     pass
 
+note = """
+should be implemented for debugging purposes. Low priority
+"""
 def set_schedule_callback(callable):
     """
     set_schedule_callback(callable) -- install a callback for scheduling.
@@ -112,7 +143,13 @@
     Pass None to switch monitoring off again.
     """
     pass
-
+
+note = """
+this was an experiment on deriving from a module.
+The idea was to make runcount and current into properties.
+__tasklet__ and __channel__ are also not used.
+It is ok to ignore these.
+"""
 class slpmodule(object):
     """
     The stackless module has a special type derived from
@@ -124,7 +161,8 @@
     """
 
 # class tasklet: see below
-
+
+note = 'drop'
 def test_cframe(switches, words=0):
     """
     test_cframe(switches, words=0) -- a builtin testing function that does 
@@ -140,6 +178,7 @@
     """
     pass
 
+note = 'drop'
 def test_cframe_nr(switches):
     """
     test_cframe_nr(switches) -- a builtin testing function that does nothing
@@ -149,6 +188,7 @@
     """
     pass
 
+note = 'drop'
 def test_outside():
     """
     test_outside() -- a builtin testing function.
@@ -182,6 +222,12 @@
     maintasklet = mt
     coro_reg[c] = mt
 
+note = """
+It is not needed to implement the watchdog feature right now.
+But run should be supported in the way the docstring says.
+The runner is always main, which must be removed while
+running all the tasklets. The implementation below is wrong.
+"""
 def run():
     """
     run_watchdog(timeout) -- run tasklets until they are all
@@ -194,7 +240,13 @@
     If an exception occours, it will be passed to the main tasklet.
     """
     schedule()
-
+
+note = """
+I don't see why coro_reg is needed.
+tasklets should ideally inherit from coroutine.
+This will create unwanted attributes, but they will
+go away when we port this to interp-leve.
+"""
 def getcurrent():
     """
     getcurrent() -- return the currently executing tasklet.
@@ -225,18 +277,25 @@
 #    __slots__ = ['alive','atomic','block_trap','blocked','frame',
 #                 'ignore_nesting','is_current','is_main',
 #                 'nesting_level','next','paused','prev','recursion_depth',
-#                 'restorable','scheduled','thread_id']
+#                 'restorable','scheduled','thread_id']
+
+## note: most of the above should be properties
 
-    def __init__(self,func=None):
+    def __init__(self, func=None):
+        ## note: this field should reuse tempval to save space
         self._func = func
 
-    def __call__(self,*argl,**argd):
+    def __call__(self, *argl, **argd):
+        ## note: please inherit
+        ## note: please use spaces after comma :-)
+        ## note: please express this using bind and setup
         self._coro = c = coroutine()
         c.bind(self._func,*argl,**argd)
         coro_reg[c] = self
         self.insert()
         return self
-
+
+    ## note: deprecated
     def become(self, retval=None):
         """
         t.become(retval) -- catch the current running frame in a tasklet.
@@ -247,7 +306,8 @@
         If retval is not given, the tasklet is used as default.
         """
         pass
-
+
+    ## note: __init__ should use this
     def bind(self):
         """
         Binding a tasklet to a callable object.
@@ -258,6 +318,7 @@
         """
         pass
 
+    ## note: deprecated
     def capture(self, retval=None):
         """
         t.capture(retval) -- capture the current running frame in a tasklet,
@@ -266,6 +327,7 @@
         """
         pass
 
+    ## note: this is not part of the interface, please drop it
     cstate = None
 
     def insert(self):
@@ -275,7 +337,8 @@
         Blocked tasklets need to be reactivated by channels.
         """
         scheduler.insert(self)
-
+
+    ## note: this is needed. please call coroutine.kill()
     def kill(self):
         """
         tasklet.kill -- raise a TaskletExit exception for the tasklet.
@@ -285,7 +348,8 @@
         the tasklet will silently die.
         """
         pass
-
+
+    ## note: see the C implementation about how to use bombs
     def raise_exception(self, exc, value):
         """
         tasklet.raise_exception(exc, value) -- raise an exception for the 
@@ -310,9 +374,13 @@
         Run this tasklet, given that it isn't blocked.
         Blocked tasks need to be reactivated by channels.
         """
-        scheduler.setnexttask(self)
+        scheduler.setnexttask(self)
+        ## note: please support different schedulers
+        ## and don't mix calls to module functions with scheduler methods.
         schedule()
-
+
+    ## note: needed at some point. right now just a property
+    ## the stackless_flags should all be supported
     def set_atomic(self):
         """
         t.set_atomic(flag) -- set tasklet atomic status and return current one.
@@ -329,7 +397,8 @@
         See set_ignore_nesting.
         """
         pass
-
+
+    ## note: see above
     def set_ignore_nesting(self,flag):
         """
         t.set_ignore_nesting(flag) -- set tasklet ignore_nesting status and 
@@ -343,13 +412,19 @@
             t.set_ignore_nesting(tmp)
         """
         pass
-
+
+    ## note
+    ## tasklet(func)(*args, **kwds)
+    ## is identical to
+    ## t = tasklet; t.bind(func); t.setup(*args, **kwds)
     def setup(self,*argl,**argd):
         """
         supply the parameters for the callable
         """
         pass
-
+
+    ## note: this attribute should always be there.
+    ## no class default needed.
     tempval = None
 
 class channel(object):
@@ -365,10 +440,12 @@
 #                 'schedule_all']
 
     def __init__(self):
-        self.balance = 0
+        self.balance = 0
+        ## note: this is a deque candidate.
         self._readq = []
         self._writeq = []
-
+
+    ## note: needed
     def close(self):
         """
         channel.close() -- stops the channel from enlarging its queue.
@@ -378,12 +455,14 @@
         """
         pass
 
+    ## note: needed. iteration over a channel reads it all.
     def next(self):
         """
         x.next() -> the next value, or raise StopIteration
         """
         pass
 
+    ## note: needed
     def open(self):
         """
         channel.open() -- reopen a channel. See channel.close.
@@ -426,7 +505,8 @@
             nt, self._readq = self._readq[0], self._readq[1:]
             scheduler.priorityinsert(nt)
         schedule()
-
+
+    ## note: see the C implementation on how to use bombs.
     def send_exception(self, exc, value):
         """
         channel.send_exception(exc, value) -- send an exception over the 
@@ -434,7 +514,8 @@
         Behavior is like channel.send, but that the receiver gets an exception.
         """
         pass
-
+
+    ## needed
     def send_sequence(self, value):
         """
         channel.send(value) -- send a value over the channel.
@@ -447,8 +528,10 @@
 
 
 class Scheduler(object):
-    def __init__(self):
-        self.tasklist = []
+    def __init__(self):
+        ## note: better use a deque
+        self.tasklist = []
+        ## note: in terms of moving to interplevel, I would not do that
         self.nexttask = None 
 
     def empty(self):
@@ -508,3 +591,6 @@
 
 scheduler = Scheduler()
 __init()
+
+## note: nice work :-)
+


From tismer at codespeak.net  Sat May 13 17:00:30 2006
From: tismer at codespeak.net (tismer at codespeak.net)
Date: Sat, 13 May 2006 17:00:30 +0200 (CEST)
Subject: [pypy-svn] r27179 - pypy/dist/pypy/module/stackless/test
Message-ID: <20060513150030.0C997100AA@code0.codespeak.net>

Author: tismer
Date: Sat May 13 17:00:29 2006
New Revision: 27179

Modified:
   pypy/dist/pypy/module/stackless/test/stackless_.py
Log:
some more comments. I don't think this is the right time to redesign stuff
too much. probably we should keep the linked lists and redesign later.

Modified: pypy/dist/pypy/module/stackless/test/stackless_.py
==============================================================================
--- pypy/dist/pypy/module/stackless/test/stackless_.py	(original)
+++ pypy/dist/pypy/module/stackless/test/stackless_.py	Sat May 13 17:00:29 2006
@@ -279,7 +279,15 @@
 #                 'nesting_level','next','paused','prev','recursion_depth',
 #                 'restorable','scheduled','thread_id']
 
-## note: most of the above should be properties
+    ## note: most of the above should be properties
+
+    ## note that next and prev are not here.
+    ## should this be implemented, or better not?
+    ## I think yes. it is easier to keep the linkage.
+    ## tasklets gave grown this, and we can do different
+    ## classes, later.
+    ## well, it is a design question, but fow now probably simplest
+    ## to just copy that.
 
     def __init__(self, func=None):
         ## note: this field should reuse tempval to save space
@@ -580,7 +588,10 @@
     def setnexttask(self,task):
         if task not in self.tasklist:
             self.tasklist.insert(task)
-        try:
+        try:
+            ## note: this is inefficient
+            ## please use the flag attributes
+            ## a tasklet 'knows' if it is in something
             i = self.tasklist.index(task)
             self.nexttask = i
         except IndexError:pass


From arigo at codespeak.net  Sat May 13 17:18:49 2006
From: arigo at codespeak.net (arigo at codespeak.net)
Date: Sat, 13 May 2006 17:18:49 +0200 (CEST)
Subject: [pypy-svn] r27180 - pypy/dist/pypy/translator/backendopt
Message-ID: <20060513151849.AD746100B2@code0.codespeak.net>

Author: arigo
Date: Sat May 13 17:18:48 2006
New Revision: 27180

Modified:
   pypy/dist/pypy/translator/backendopt/propagate.py
Log:
Protect these operations like getsubstruct.


Modified: pypy/dist/pypy/translator/backendopt/propagate.py
==============================================================================
--- pypy/dist/pypy/translator/backendopt/propagate.py	(original)
+++ pypy/dist/pypy/translator/backendopt/propagate.py	Sat May 13 17:18:48 2006
@@ -141,7 +141,8 @@
             CONTAINER = op.args[0].concretetype.TO
             if CONTAINER._hints.get('immutable'):
                 return False
-        if op.opname in ("getsubstruct", "getarraysubstruct"):
+        if op.opname in ("getsubstruct", "getarraysubstruct",
+                         "direct_fieldptr", "direct_arrayitems"):
             # this is needed so that the parent of the result (op.args[0])
             # does not go away after the op is folded. see test_dont_fold_getsubstruct
             if not var_needsgc(op.result):


From pedronis at codespeak.net  Sat May 13 18:04:20 2006
From: pedronis at codespeak.net (pedronis at codespeak.net)
Date: Sat, 13 May 2006 18:04:20 +0200 (CEST)
Subject: [pypy-svn] r27181 - in pypy/dist/pypy: rpython rpython/memory
	rpython/module translator/stackless translator/stackless/test
Message-ID: <20060513160420.600CA100A9@code0.codespeak.net>

Author: pedronis
Date: Sat May 13 18:04:18 2006
New Revision: 27181

Modified:
   pypy/dist/pypy/rpython/extfunctable.py
   pypy/dist/pypy/rpython/memory/gctransform.py
   pypy/dist/pypy/rpython/module/ll_stack.py
   pypy/dist/pypy/rpython/rstack.py
   pypy/dist/pypy/translator/stackless/code.py
   pypy/dist/pypy/translator/stackless/test/test_depth.py
   pypy/dist/pypy/translator/stackless/transform.py
Log:
reusing stack_unwind to return a value was a bad idea, it breaks assumption for the non-stackless and refcounting code.
introudce stack_capture instead.



Modified: pypy/dist/pypy/rpython/extfunctable.py
==============================================================================
--- pypy/dist/pypy/rpython/extfunctable.py	(original)
+++ pypy/dist/pypy/rpython/extfunctable.py	Sat May 13 18:04:18 2006
@@ -250,7 +250,8 @@
 declare(rstack.stack_frames_depth, int, 'll_stackless/stack_frames_depth')
 declare(rstack.stack_too_big, bool, 'll_stack/too_big')
 declare(rstack.stack_check, noneannotation, 'll_stack/check')
-declare(rstack.stack_unwind, rstack.frame_stack_top, 'll_stack/unwind')
+declare(rstack.stack_unwind, noneannotation, 'll_stack/unwind')
+declare(rstack.stack_capture, rstack.frame_stack_top, 'll_stack/capture')
 frametop_type_info = declaregcptrtype(rstack.frame_stack_top,'frame_stack_top',
                                         switch = (rstack.frame_stack_top,
                                                   'll_stackless/switch'),

Modified: pypy/dist/pypy/rpython/memory/gctransform.py
==============================================================================
--- pypy/dist/pypy/rpython/memory/gctransform.py	(original)
+++ pypy/dist/pypy/rpython/memory/gctransform.py	Sat May 13 18:04:18 2006
@@ -1152,7 +1152,7 @@
     use_stackless = True
 
     def build_stack_root_iterator(self):
-        from pypy.rpython.rstack import stack_unwind
+        from pypy.rpython.rstack import stack_capture
         sizeofaddr = llmemory.sizeof(llmemory.Address)
         gcdata = self.gcdata
 
@@ -1184,7 +1184,7 @@
                     return gcdata.static_roots[i]
                 if self.provide_current_frame:
                     self.provide_current_frame = False
-                    frame = stack_unwind()
+                    frame = stack_capture()
                     return llmemory.cast_ptr_to_adr(frame)
                 return llmemory.NULL
 

Modified: pypy/dist/pypy/rpython/module/ll_stack.py
==============================================================================
--- pypy/dist/pypy/rpython/module/ll_stack.py	(original)
+++ pypy/dist/pypy/rpython/module/ll_stack.py	Sat May 13 18:04:18 2006
@@ -5,9 +5,13 @@
 ll_stack_too_big.suggested_primitive = True
 
 def ll_stack_unwind():
-    return rstack.stack_unwind()
+    rstack.stack_unwind()
 ll_stack_unwind.suggested_primitive = True
 
+def ll_stack_capture():
+    return rstack.stack_capture()
+ll_stack_capture.suggested_primitive = True
+
 def ll_stack_check():
     if ll_stack_too_big():
         ll_stack_unwind()

Modified: pypy/dist/pypy/rpython/rstack.py
==============================================================================
--- pypy/dist/pypy/rpython/rstack.py	(original)
+++ pypy/dist/pypy/rpython/rstack.py	Sat May 13 18:04:18 2006
@@ -8,6 +8,9 @@
 def stack_unwind():
     raise RuntimeError("cannot unwind stack in non-translated versions")
 
+def stack_capture():
+    raise RuntimeError("cannot unwind stack in non-translated versions")
+
 def stack_frames_depth():
     return len(inspect.stack())
 

Modified: pypy/dist/pypy/translator/stackless/code.py
==============================================================================
--- pypy/dist/pypy/translator/stackless/code.py	(original)
+++ pypy/dist/pypy/translator/stackless/code.py	Sat May 13 18:04:18 2006
@@ -154,6 +154,28 @@
     else:
         # STATE 0: now the stack is unwound.  That was the goal.
         # Return to caller.
+        global_state.top = frame.null_state
+        global_state.restart_substate = -1
+        
+ll_stack_unwind.stackless_explicit = True
+
+INDEX_UNWIND = frame.RestartInfo.add_prebuilt(ll_stack_unwind,
+                                               [EMPTY_STATE])
+
+# ____________________________________________________________
+
+def ll_stack_capture():
+    if global_state.restart_substate == -1:
+        # normal entry point for stack_frames_depth()
+        # first unwind the stack in the usual way
+        u = UnwindException()
+        s = lltype.malloc(EMPTY_STATE).header
+        s.f_restart = INDEX_CAPTURE
+        add_frame_state(u, s)
+        raise u    # goes to STATE 0 below
+    else:
+        # STATE 0: now the stack is unwound.  That was the goal.
+        # Return to caller.
         cur = global_state.top
         global_state.top = frame.null_state
         global_state.restart_substate = -1
@@ -161,10 +183,10 @@
         # The StacklessFrameworkGCTransformer uses this for introspection.
         return lltype.cast_opaque_ptr(frame.OPAQUE_STATE_HEADER_PTR,
                                       cur.f_back)
-ll_stack_unwind.stackless_explicit = True
+ll_stack_capture.stackless_explicit = True
 
-INDEX_UNWIND = frame.RestartInfo.add_prebuilt(ll_stack_unwind,
-                                              [EMPTY_STATE])
+INDEX_CAPTURE = frame.RestartInfo.add_prebuilt(ll_stack_capture,
+                                               [EMPTY_STATE])
 
 # ____________________________________________________________
 

Modified: pypy/dist/pypy/translator/stackless/test/test_depth.py
==============================================================================
--- pypy/dist/pypy/translator/stackless/test/test_depth.py	(original)
+++ pypy/dist/pypy/translator/stackless/test/test_depth.py	Sat May 13 18:04:18 2006
@@ -88,9 +88,9 @@
     res = run_stackless_function(fn)
     assert res == 15
 
-def test_stack_unwind_retval():
+def test_stack_capture():
     def fn():
-        frame = rstack.stack_unwind()
+        frame = rstack.stack_capture()
         return int(bool(frame))
 
     res = llinterp_stackless_function(fn)

Modified: pypy/dist/pypy/translator/stackless/transform.py
==============================================================================
--- pypy/dist/pypy/translator/stackless/transform.py	(original)
+++ pypy/dist/pypy/translator/stackless/transform.py	Sat May 13 18:04:18 2006
@@ -112,7 +112,7 @@
     def analyze_external_call(self, op):
         callable = op.args[0].value._obj._callable
         #assert getattr(callable, 'suggested_primitive', False)
-        return callable in [ll_stack.ll_stack_unwind,
+        return callable in [ll_stack.ll_stack_unwind, ll_stack.ll_stack_capture,
                             ll_stackless.ll_stackless_stack_frames_depth,
                             ll_stackless.ll_stackless_switch]
                             
@@ -195,8 +195,12 @@
                     code.ll_frame_clone, [s_StatePtr], s_StatePtr),
             ll_stack.ll_stack_unwind:
                 mixlevelannotator.constfunc(
-                    code.ll_stack_unwind, [], s_StatePtr),
+                    code.ll_stack_unwind, [], annmodel.s_None),
+            ll_stack.ll_stack_capture:
+                mixlevelannotator.constfunc(
+                    code.ll_stack_capture, [], s_StatePtr),
             }
+
         self.yield_current_frame_to_caller_ptr = mixlevelannotator.constfunc(
             code.yield_current_frame_to_caller, [], s_StatePtr)
 


From pedronis at codespeak.net  Sat May 13 18:39:29 2006
From: pedronis at codespeak.net (pedronis at codespeak.net)
Date: Sat, 13 May 2006 18:39:29 +0200 (CEST)
Subject: [pypy-svn] r27182 - pypy/dist/pypy/translator/backendopt
Message-ID: <20060513163929.DD704100AA@code0.codespeak.net>

Author: pedronis
Date: Sat May 13 18:39:28 2006
New Revision: 27182

Modified:
   pypy/dist/pypy/translator/backendopt/graphanalyze.py
Log:
bug in graphanalyzer



Modified: pypy/dist/pypy/translator/backendopt/graphanalyze.py
==============================================================================
--- pypy/dist/pypy/translator/backendopt/graphanalyze.py	(original)
+++ pypy/dist/pypy/translator/backendopt/graphanalyze.py	Sat May 13 18:39:28 2006
@@ -66,6 +66,7 @@
                     return True
             for exit in block.exits:
                 if self.analyze_link(graph, exit):
+                    self.analyzed_calls[graph] = True
                     return True
         self.analyzed_calls[graph] = False
         return False


From pedronis at codespeak.net  Sat May 13 18:40:36 2006
From: pedronis at codespeak.net (pedronis at codespeak.net)
Date: Sat, 13 May 2006 18:40:36 +0200 (CEST)
Subject: [pypy-svn] r27183 - pypy/dist/pypy/translator/stackless
Message-ID: <20060513164036.9DFDC100B2@code0.codespeak.net>

Author: pedronis
Date: Sat May 13 18:40:35 2006
New Revision: 27183

Modified:
   pypy/dist/pypy/translator/stackless/transform.py
Log:
stackless operations are known to need unwind logic around them.

this should fix  test_tasklets.



Modified: pypy/dist/pypy/translator/stackless/transform.py
==============================================================================
--- pypy/dist/pypy/translator/stackless/transform.py	(original)
+++ pypy/dist/pypy/translator/stackless/transform.py	Sat May 13 18:40:35 2006
@@ -390,10 +390,12 @@
             return newop
 
         while i < len(block.operations):
+            stackless_op = False
             op = block.operations[i]
             if op.opname == 'yield_current_frame_to_caller':
                 op = replace_with_call(self.yield_current_frame_to_caller_ptr)
-
+                stackless_op = True
+                
             if (op.opname in ('direct_call', 'indirect_call') or
                 op.opname.startswith('malloc')):
                 # trap calls to stackless-related suggested primitives
@@ -401,8 +403,9 @@
                     func = getattr(op.args[0].value._obj, '_callable', None)
                     if func in self.suggested_primitives:
                         op = replace_with_call(self.suggested_primitives[func])
-
-                if not self.analyzer.analyze(op):
+                        stackless_op = True
+                        
+                if not stackless_op and not self.analyzer.analyze(op):
                     i += 1
                     continue
 


From arigo at codespeak.net  Sat May 13 18:48:22 2006
From: arigo at codespeak.net (arigo at codespeak.net)
Date: Sat, 13 May 2006 18:48:22 +0200 (CEST)
Subject: [pypy-svn] r27184 - in pypy/dist/pypy: rpython translator/backendopt
Message-ID: <20060513164822.6FC16100AA@code0.codespeak.net>

Author: arigo
Date: Sat May 13 18:48:21 2006
New Revision: 27184

Modified:
   pypy/dist/pypy/rpython/llinterp.py
   pypy/dist/pypy/translator/backendopt/propagate.py
Log:
Major headaches for minor clean-ups.


Modified: pypy/dist/pypy/rpython/llinterp.py
==============================================================================
--- pypy/dist/pypy/rpython/llinterp.py	(original)
+++ pypy/dist/pypy/rpython/llinterp.py	Sat May 13 18:48:21 2006
@@ -36,9 +36,7 @@
 class LLInterpreter(object):
     """ low level interpreter working with concrete values. """
 
-    TRACING = True
-
-    def __init__(self, typer, heap=lltype):
+    def __init__(self, typer, heap=lltype, tracing=True):
         self.bindings = {}
         self.typer = typer
         self.heap = heap  #module that provides malloc, etc for lltypes
@@ -51,7 +49,7 @@
         if hasattr(heap, "prepare_graphs_and_create_gc"):
             flowgraphs = typer.annotator.translator.graphs
             self.gc = heap.prepare_graphs_and_create_gc(self, flowgraphs)
-        if self.TRACING:
+        if tracing:
             self.tracer = Tracer()
 
     def eval_graph(self, graph, args=()):

Modified: pypy/dist/pypy/translator/backendopt/propagate.py
==============================================================================
--- pypy/dist/pypy/translator/backendopt/propagate.py	(original)
+++ pypy/dist/pypy/translator/backendopt/propagate.py	Sat May 13 18:48:21 2006
@@ -159,7 +159,7 @@
     """do constant folding if the arguments of an operations are constants"""
     if analyzer is None:
         analyzer = CanfoldAnalyzer(translator)
-    lli = LLInterpreter(translator.rtyper)
+    lli = LLInterpreter(translator.rtyper, tracing=False)
     llframe = LLFrame(graph, None, lli)
     changed = False
     for block in graph.iterblocks():
@@ -183,7 +183,7 @@
                     res = Constant(llframe.getval(op.result))
             except (SystemExit, KeyboardInterrupt):
                 raise
-            except:
+            except:    # XXXXXXXXXXXXXXXX try to only catch TypeError
                 continue
             log.constantfolding("in graph %s, %s = %s" %
                                 (graph.name, op, res))
@@ -191,7 +191,6 @@
             block.operations[i].opname = "same_as"
             block.operations[i].args = [res]
             changed = True
-        block.operations = [op for op in block.operations if op is not None]
     if changed:
         remove_same_as(graph)
         propagate_consts(graph)
@@ -328,10 +327,6 @@
     return result
 
 def partial_folding(graph, translator, analyzer=None):
-    """this function does constant folding in the following situation:
-    a block has a link that leads to it that has only constant args. Then all
-    the operations of this block are evaluated and the link leading to the
-    block is adjusted according to the resulting value of the exitswitch"""
     if do_atmost(1000, partial_folding_once, graph, translator, analyzer):
         propagate_consts(graph)
         simplify.join_blocks(graph)


From arigo at codespeak.net  Sat May 13 18:54:43 2006
From: arigo at codespeak.net (arigo at codespeak.net)
Date: Sat, 13 May 2006 18:54:43 +0200 (CEST)
Subject: [pypy-svn] r27185 - pypy/dist/pypy/rpython/test
Message-ID: <20060513165443.357AE100AA@code0.codespeak.net>

Author: arigo
Date: Sat May 13 18:54:41 2006
New Revision: 27185

Modified:
   pypy/dist/pypy/rpython/test/test_nongc.py
Log:
Fixed import.


Modified: pypy/dist/pypy/rpython/test/test_nongc.py
==============================================================================
--- pypy/dist/pypy/rpython/test/test_nongc.py	(original)
+++ pypy/dist/pypy/rpython/test/test_nongc.py	Sat May 13 18:54:41 2006
@@ -186,7 +186,6 @@
     assert res == 0x0200
 
 def test_rtype_nongc_object():
-    from pypy.rpython.memory.lladdress import address
     class TestClass(object):
         _alloc_flavor_ = "raw"
         def __init__(self, a):
@@ -204,5 +203,6 @@
     assert isinstance(s, annmodel.SomeAddress)
     rtyper = RPythonTyper(a)
     rtyper.specialize()
-##     res = interpret(malloc_and_free, [address()])
-##     assert res == address()
+##     from pypy.rpython.memory.lladdress import _address
+##     res = interpret(malloc_and_free, [_address()])
+##     assert res == _address()


From arigo at codespeak.net  Sat May 13 19:16:16 2006
From: arigo at codespeak.net (arigo at codespeak.net)
Date: Sat, 13 May 2006 19:16:16 +0200 (CEST)
Subject: [pypy-svn] r27186 - in pypy/dist/pypy: annotation objspace/flow
	translator/c
Message-ID: <20060513171616.8C1E3100AA@code0.codespeak.net>

Author: arigo
Date: Sat May 13 19:16:14 2006
New Revision: 27186

Modified:
   pypy/dist/pypy/annotation/description.py
   pypy/dist/pypy/objspace/flow/objspace.py
   pypy/dist/pypy/translator/c/pyobj.py
Log:
Fix the test_wrapping failures.  The old behavior captured in the PyObject
wrapper strange unannotated functions and methods if they were specialized,
e.g. the ones taking *args.  Skip these now.


Modified: pypy/dist/pypy/annotation/description.py
==============================================================================
--- pypy/dist/pypy/annotation/description.py	(original)
+++ pypy/dist/pypy/annotation/description.py	Sat May 13 19:16:14 2006
@@ -158,6 +158,9 @@
     simplify_desc_set = staticmethod(simplify_desc_set)
 
 
+class NoStandardGraph(Exception):
+    """The function doesn't have a single standard non-specialized graph."""
+
 class FunctionDesc(Desc):
     knowntype = types.FunctionType
     overridden = False
@@ -192,8 +195,13 @@
         return graph
 
     def getuniquegraph(self):
-        assert len(self._cache) == 1
-        return self._cache.values()[0]
+        if len(self._cache) != 1:
+            raise NoStandardGraph(self)
+        [graph] = self._cache.values()
+        if (graph.signature != self.signature or
+            graph.defaults  != self.defaults):
+            raise NoStandardGraph(self)
+        return graph
 
     def cachedgraph(self, key, alt_name=None, builder=None):
         try:

Modified: pypy/dist/pypy/objspace/flow/objspace.py
==============================================================================
--- pypy/dist/pypy/objspace/flow/objspace.py	(original)
+++ pypy/dist/pypy/objspace/flow/objspace.py	Sat May 13 19:16:14 2006
@@ -256,7 +256,7 @@
         # so that it becomes even more interchangeable with the function
         # itself
         graph.signature = cpython_code_signature(code)
-        graph.defaults = func.func_defaults
+        graph.defaults = func.func_defaults or ()
         self.setup_executioncontext(ec)
         ec.build_flow()
         checkgraph(graph)

Modified: pypy/dist/pypy/translator/c/pyobj.py
==============================================================================
--- pypy/dist/pypy/translator/c/pyobj.py	(original)
+++ pypy/dist/pypy/translator/c/pyobj.py	Sat May 13 19:16:14 2006
@@ -3,6 +3,7 @@
 from types import FunctionType, CodeType, InstanceType, ClassType
 
 from pypy.objspace.flow.model import Variable, Constant, FunctionGraph
+from pypy.annotation.description import NoStandardGraph
 from pypy.translator.gensupp import builtin_base, builtin_type_base
 from pypy.translator.c.support import log
 from pypy.translator.c.wrapper import gen_wrapper, new_method_graph
@@ -215,9 +216,12 @@
         if self.shouldskipfunc(func):
             return self.skipped_function(func)
 
-        fwrapper = gen_wrapper(func, self.translator,
-                               newname=self.name_for_meth.get(func, func.__name__),
-                               as_method=func in self.is_method)
+        try:
+            fwrapper = gen_wrapper(func, self.translator,
+                                   newname=self.name_for_meth.get(func, func.__name__),
+                                   as_method=func in self.is_method)
+        except NoStandardGraph:
+            return self.skipped_function(func)
         pycfunctionobj = self.uniquename('gfunc_' + func.__name__)
         self.wrappers[pycfunctionobj] = func.__name__, self.getvalue(fwrapper), func.__doc__
         return pycfunctionobj


From antocuni at codespeak.net  Sat May 13 20:06:54 2006
From: antocuni at codespeak.net (antocuni at codespeak.net)
Date: Sat, 13 May 2006 20:06:54 +0200 (CEST)
Subject: [pypy-svn] r27187 - pypy/dist/pypy/rpython/test
Message-ID: <20060513180654.3B18B100AA@code0.codespeak.net>

Author: antocuni
Date: Sat May 13 20:06:48 2006
New Revision: 27187

Modified:
   pypy/dist/pypy/rpython/test/test_rstr.py
Log:
Added one more test for ootypesystem rstr



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 May 13 20:06:48 2006
@@ -122,13 +122,13 @@
             res = self.interpret(fn, [ch])
             assert res == fn(ch)
 
-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
+    def test_char_compare(self):
+        res = self.interpret(lambda c1, c2: c1 == c2,  ['a', 'b'])
+        assert res is False
+        res = self.interpret(lambda c1, c2: c1 == c2,  ['a', 'a'])
+        assert res is True
+        res = self.interpret(lambda c1, c2: c1 <= c2,  ['z', 'a'])
+        assert res is False
 
 def test_char_mul():
     def fn(c, mul):


From arigo at codespeak.net  Sat May 13 20:11:00 2006
From: arigo at codespeak.net (arigo at codespeak.net)
Date: Sat, 13 May 2006 20:11:00 +0200 (CEST)
Subject: [pypy-svn] r27188 - in pypy/dist/pypy: annotation rpython
	rpython/lltypesystem rpython/lltypesystem/test rpython/test
	translator/c/test
Message-ID: <20060513181100.5A9E2100AA@code0.codespeak.net>

Author: arigo
Date: Sat May 13 20:10:56 2006
New Revision: 27188

Modified:
   pypy/dist/pypy/annotation/builtin.py
   pypy/dist/pypy/rpython/lltypesystem/lltype.py
   pypy/dist/pypy/rpython/lltypesystem/test/test_lltype.py
   pypy/dist/pypy/rpython/rbuiltin.py
   pypy/dist/pypy/rpython/test/test_rptr.py
   pypy/dist/pypy/translator/c/test/test_newgc.py
Log:
(pedronis, arigo)
Added lltype.free() as a function, and support for it and for flavored mallocs
here and there.


Modified: pypy/dist/pypy/annotation/builtin.py
==============================================================================
--- pypy/dist/pypy/annotation/builtin.py	(original)
+++ pypy/dist/pypy/annotation/builtin.py	Sat May 13 20:10:56 2006
@@ -375,15 +375,25 @@
 from pypy.annotation.model import SomePtr
 from pypy.rpython.lltypesystem import lltype
 
-def malloc(T, n=None):
+def malloc(T, n=None, s_flavor=None):
     assert n is None or n.knowntype == int
     assert T.is_constant()
     if n is not None:
         n = 1
-    p = lltype.malloc(T.const, n)
+    if s_flavor is None:
+        p = lltype.malloc(T.const, n)
+    else:
+        assert s_flavor.is_constant()
+        p = lltype.malloc(T.const, n, s_flavor.const)
     r = SomePtr(lltype.typeOf(p))
     return r
 
+def free(s_p, s_flavor):
+    assert s_flavor.is_constant()
+    T = s_p.ll_ptrtype.TO
+    p = lltype.malloc(T, flavor=s_flavor.const)
+    lltype.free(p, flavor=s_flavor.const)
+
 def typeOf(s_val):
     lltype = annotation_to_lltype(s_val, info="in typeOf(): ")
     return immutablevalue(lltype)
@@ -446,6 +456,7 @@
     return immutablevalue(lltype.Ptr(T.const))
 
 BUILTIN_ANALYZERS[lltype.malloc] = malloc
+BUILTIN_ANALYZERS[lltype.free] = free
 BUILTIN_ANALYZERS[lltype.typeOf] = typeOf
 BUILTIN_ANALYZERS[lltype.cast_primitive] = cast_primitive
 BUILTIN_ANALYZERS[lltype.nullptr] = nullptr

Modified: pypy/dist/pypy/rpython/lltypesystem/lltype.py
==============================================================================
--- pypy/dist/pypy/rpython/lltypesystem/lltype.py	(original)
+++ pypy/dist/pypy/rpython/lltypesystem/lltype.py	Sat May 13 20:10:56 2006
@@ -1336,9 +1336,12 @@
     solid = immortal or not flavor.startswith('gc') # immortal or non-gc case
     return _ptr(Ptr(T), o, solid)
 
-def flavored_malloc(flavor, T, n=None): # avoids keyword argument usage
-    return malloc(T, n, flavor=flavor)
-    
+def free(p, flavor):
+    if flavor.startswith('gc'):
+        raise TypeError, "gc flavor free"
+    T = typeOf(p)
+    if not isinstance(T, Ptr) or p._needsgc():
+        raise TypeError, "free(): only for pointers to non-gc containers"
 
 def functionptr(TYPE, name, **attrs):
     if not isinstance(TYPE, FuncType):

Modified: pypy/dist/pypy/rpython/lltypesystem/test/test_lltype.py
==============================================================================
--- pypy/dist/pypy/rpython/lltypesystem/test/test_lltype.py	(original)
+++ pypy/dist/pypy/rpython/lltypesystem/test/test_lltype.py	Sat May 13 20:10:56 2006
@@ -429,6 +429,11 @@
     p = malloc(S, flavor="raw")
     assert typeOf(p).TO == S
     assert not isweak(p, S)
+    free(p, flavor="raw")
+    T = GcStruct('T', ('y', Signed))
+    p = malloc(T, flavor="gc")
+    assert typeOf(p).TO == T
+    assert not isweak(p, T)
     
 def test_opaque():
     O = OpaqueType('O')

Modified: pypy/dist/pypy/rpython/rbuiltin.py
==============================================================================
--- pypy/dist/pypy/rpython/rbuiltin.py	(original)
+++ pypy/dist/pypy/rpython/rbuiltin.py	Sat May 13 20:10:56 2006
@@ -298,16 +298,26 @@
 BUILTIN_TYPER[object.__init__] = rtype_object__init__
 # annotation of low-level types
 
-def rtype_malloc(hop):
+def rtype_malloc(hop, i_flavor=None):
     assert hop.args_s[0].is_constant()
-    if hop.nb_args == 1:
-        vlist = hop.inputargs(lltype.Void)
-        return hop.genop('malloc', vlist,
-                         resulttype = hop.r_result.lowleveltype)
-    else:
-        vlist = hop.inputargs(lltype.Void, lltype.Signed)
-        return hop.genop('malloc_varsize', vlist,
-                         resulttype = hop.r_result.lowleveltype)
+    vlist = [hop.inputarg(lltype.Void, arg=0)]
+    opname = 'malloc'
+    positional_args = hop.nb_args
+    if i_flavor is not None:
+        assert i_flavor == hop.nb_args-1
+        positional_args -= 1
+        vlist.insert(0, hop.inputarg(lltype.Void, arg=i_flavor))
+        opname = 'flavored_' + opname
+    if positional_args == 2:
+        vlist.append(hop.inputarg(lltype.Signed, arg=1))
+        opname += '_varsize'
+    return hop.genop(opname, vlist, resulttype = hop.r_result.lowleveltype)
+
+def rtype_free(hop, i_flavor):
+    assert i_flavor == 1
+    vlist = hop.inputargs(hop.args_r[0], lltype.Void)
+    vlist.reverse()   # just for confusion
+    hop.genop('flavored_free', vlist)
 
 def rtype_const_result(hop):
     return hop.inputconst(hop.r_result.lowleveltype, hop.s_result.const)
@@ -420,6 +430,7 @@
                  resulttype = rptr.PtrRepr(lltype.Ptr(lltype.RuntimeTypeInfo)))
 
 BUILTIN_TYPER[lltype.malloc] = rtype_malloc
+BUILTIN_TYPER[lltype.free] = rtype_free
 BUILTIN_TYPER[lltype.cast_primitive] = rtype_cast_primitive
 BUILTIN_TYPER[lltype.cast_pointer] = rtype_cast_pointer
 BUILTIN_TYPER[lltype.cast_opaque_ptr] = rtype_cast_opaque_ptr

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	Sat May 13 20:10:56 2006
@@ -160,3 +160,24 @@
     assert res is False
     res = interpret(fn, [5])
     assert res is True
+
+def test_flavored_malloc():
+    T = GcStruct('T', ('y', Signed))
+    def fn(n):
+        p = malloc(T, flavor='gc')
+        p.y = n
+        return p.y
+
+    res = interpret(fn, [232])
+    assert res == 232
+
+    S = Struct('S', ('x', Signed))
+    def fn(n):
+        p = malloc(S, flavor='whatever')
+        p.x = n
+        result = p.x
+        free(p, flavor='whatever')
+        return n
+
+    res = interpret(fn, [23])
+    assert res == 23

Modified: pypy/dist/pypy/translator/c/test/test_newgc.py
==============================================================================
--- pypy/dist/pypy/translator/c/test/test_newgc.py	(original)
+++ pypy/dist/pypy/translator/c/test/test_newgc.py	Sat May 13 20:10:56 2006
@@ -532,6 +532,33 @@
         res = fn()
         assert res == -70
 
+    def test_framework_malloc_raw(self):
+        A = lltype.Struct('A', ('value', lltype.Signed))
+
+        def f():
+            p = lltype.malloc(A, flavor='raw')
+            p.value = 123
+            llop.gc__collect(lltype.Void)
+            res = p.value
+            lltype.free(p, flavor='raw')
+            return res
+        fn = self.getcompiled(f)
+        res = fn()
+        assert res == 123
+
+    def test_framework_malloc_gc(self):
+        py.test.skip('in-progress')
+        A = lltype.GcStruct('A', ('value', lltype.Signed))
+
+        def f():
+            p = lltype.malloc(A, flavor='gc')
+            p.value = 123
+            llop.gc__collect(lltype.Void)
+            return p.value
+        fn = self.getcompiled(f)
+        res = fn()
+        assert res == 123
+
 class TestUsingStacklessFramework(TestUsingFramework):
     from pypy.translator.c.gc import StacklessFrameworkGcPolicy as gcpolicy
 


From antocuni at codespeak.net  Sat May 13 20:19:09 2006
From: antocuni at codespeak.net (antocuni at codespeak.net)
Date: Sat, 13 May 2006 20:19:09 +0200 (CEST)
Subject: [pypy-svn] r27189 - in pypy/dist/pypy/rpython/ootypesystem: . test
Message-ID: <20060513181909.3B48E100AA@code0.codespeak.net>

Author: antocuni
Date: Sat May 13 20:19:00 2006
New Revision: 27189

Modified:
   pypy/dist/pypy/rpython/ootypesystem/ootype.py
   pypy/dist/pypy/rpython/ootypesystem/test/test_oostring.py
Log:
Added a new type to ootype: StringBuilder, used for dynamically
building strings.



Modified: pypy/dist/pypy/rpython/ootypesystem/ootype.py
==============================================================================
--- pypy/dist/pypy/rpython/ootypesystem/ootype.py	(original)
+++ pypy/dist/pypy/rpython/ootypesystem/ootype.py	Sat May 13 20:19:00 2006
@@ -294,6 +294,29 @@
     def _specialize(self, generic_types):
         return self
 
+# WARNING: the name 'StringBuilder' is rebound at the end of file
+class StringBuilder(BuiltinADTType):
+    def __init__(self):
+        self._null = _null_string_builder(self)
+        self._GENERIC_METHODS = frozendict({
+            "ll_allocate": Meth([Signed], Void),
+            "ll_append_char": Meth([Char], Void),
+            "ll_append": Meth([String], Void),
+            "ll_build": Meth([], String),
+            })
+        self._setup_methods({})
+
+    def _defl(self):
+        return self._null
+
+    def _example(self):
+        return self._defl()
+
+    def _get_interp_class(self):
+        return _string_builder
+
+    def _specialize(self, generic_types):
+        return self
 
 class List(BuiltinADTType):
     # placeholders for types
@@ -768,7 +791,6 @@
         return object.__getattribute__(self, name)
 
 
-
 class _string(_builtin_type):
 
     def __init__(self, STRING, value = ''):
@@ -816,6 +838,31 @@
     def __init__(self, STRING):
         self.__dict__["_TYPE"] = STRING
 
+class _string_builder(_builtin_type):
+    def __init__(self, STRING_BUILDER):
+        self._TYPE = STRING_BUILDER
+        self._buf = []
+
+    def ll_allocate(self, n):
+        assert isinstance(n, int)
+        # do nothing
+
+    def ll_append_char(self, ch):
+        assert isinstance(ch, str) and len(ch) == 1
+        self._buf.append(ch)
+
+    def ll_append(self, s):
+        assert isinstance(s, _string)
+        self._buf.append(s._str)
+
+    def ll_build(self):
+        return make_string(''.join(self._buf))
+
+class _null_string_builder(_null_mixin(_string_builder), _string_builder):
+    def __init__(self, STRING_BUILDER):
+        self.__dict__["_TYPE"] = STRING_BUILDER
+
+
 class _list(_builtin_type):
     def __init__(self, LIST):
         self._TYPE = LIST
@@ -1073,4 +1120,5 @@
     return DICT._is_initialized()
 
 String = String()
+StringBuilder = StringBuilder()
 ROOT = Instance('Root', None, _is_root=True)

Modified: pypy/dist/pypy/rpython/ootypesystem/test/test_oostring.py
==============================================================================
--- pypy/dist/pypy/rpython/ootypesystem/test/test_oostring.py	(original)
+++ pypy/dist/pypy/rpython/ootypesystem/test/test_oostring.py	Sat May 13 20:19:00 2006
@@ -18,3 +18,10 @@
     assert isinstance(res, ootype._list)
     assert res.ll_getitem_fast(0)._str == 'foo'
     assert res.ll_getitem_fast(1)._str == 'bar'
+
+def test_string_builder():
+    b = ootype.new(ootype.StringBuilder)
+    b.ll_append_char('a')
+    b.ll_append(ootype.make_string('bcd'))
+    res = b.ll_build()
+    assert res._str == 'abcd'


From antocuni at codespeak.net  Sat May 13 20:33:28 2006
From: antocuni at codespeak.net (antocuni at codespeak.net)
Date: Sat, 13 May 2006 20:33:28 +0200 (CEST)
Subject: [pypy-svn] r27190 - in pypy/dist/pypy/rpython: ootypesystem test
Message-ID: <20060513183328.018A7100AA@code0.codespeak.net>

Author: antocuni
Date: Sat May 13 20:33:18 2006
New Revision: 27190

Modified:
   pypy/dist/pypy/rpython/ootypesystem/ootype.py
   pypy/dist/pypy/rpython/ootypesystem/rstr.py
   pypy/dist/pypy/rpython/test/test_rstr.py
Log:
Added support for operator * and == on ootypeststem rstr.



Modified: pypy/dist/pypy/rpython/ootypesystem/ootype.py
==============================================================================
--- pypy/dist/pypy/rpython/ootypesystem/ootype.py	(original)
+++ pypy/dist/pypy/rpython/ootypesystem/ootype.py	Sat May 13 20:33:18 2006
@@ -277,7 +277,8 @@
         self._GENERIC_METHODS = frozendict({
             "ll_stritem_nonneg": Meth([Signed], Char),
             "ll_strlen": Meth([], Signed),
-            "ll_strconcat": Meth([self.SELFTYPE_T], self.SELFTYPE_T)
+            "ll_strconcat": Meth([self.SELFTYPE_T], self.SELFTYPE_T),
+            "ll_equal": Meth([self.SELFTYPE_T], Bool),
         })
         self._setup_methods(generic_types)
 
@@ -309,9 +310,6 @@
     def _defl(self):
         return self._null
 
-    def _example(self):
-        return self._defl()
-
     def _get_interp_class(self):
         return _string_builder
 
@@ -810,6 +808,10 @@
         # NOT_RPYTHON
         return make_string(self._str + s._str)
 
+    def ll_equal(self, s):
+        # NOT_RPYTON
+        return self._str == s._str
+
     # delegate missing ll_* methods to self._str
     def __getattr__(self, attr):
         if attr.startswith('ll_'):

Modified: pypy/dist/pypy/rpython/ootypesystem/rstr.py
==============================================================================
--- pypy/dist/pypy/rpython/ootypesystem/rstr.py	(original)
+++ pypy/dist/pypy/rpython/ootypesystem/rstr.py	Sat May 13 20:33:18 2006
@@ -63,6 +63,20 @@
     def ll_chr2str(ch):
         return ootype.oostring(ch)
 
+    def ll_char_mul(ch, times):
+        builder = ootype.new(ootype.StringBuilder)
+        builder.ll_allocate(times)
+        i = 0
+        while i

Author: pedronis
Date: Sat May 13 23:17:14 2006
New Revision: 27191

Modified:
   pypy/dist/pypy/annotation/annrpython.py
   pypy/dist/pypy/translator/unsimplify.py
Log:
attempt at fixing copyvar again



Modified: pypy/dist/pypy/annotation/annrpython.py
==============================================================================
--- pypy/dist/pypy/annotation/annrpython.py	(original)
+++ pypy/dist/pypy/annotation/annrpython.py	Sat May 13 23:17:14 2006
@@ -295,9 +295,12 @@
                              (self.return_bindings[arg],None, None))
                 
             self.binding_caused_by[arg] = called_from_graph
-        # XXX make this line available as a debugging option
-        ##assert not (s_value.__class__ == annmodel.SomeObject and s_value.knowntype == object) ## debug
 
+    def transfer_binding(self, v_target, v_source):
+        assert v_source in self.bindings
+        self.bindings[v_target] = self.bindings[v_source]
+        if annmodel.DEBUG:
+            self.binding_caused_by[v_target] = None
 
     def warning(self, msg, pos=None):
         if pos is None:

Modified: pypy/dist/pypy/translator/unsimplify.py
==============================================================================
--- pypy/dist/pypy/translator/unsimplify.py	(original)
+++ pypy/dist/pypy/translator/unsimplify.py	Sat May 13 23:17:14 2006
@@ -7,7 +7,7 @@
     if translator is not None:
         annotator = translator.annotator
         if annotator is not None and v in annotator.bindings:
-            annotator.setbinding(newvar, annotator.bindings[v])
+            annotator.transfer_binding(newvar, v)
     if hasattr(v, 'concretetype'):
         newvar.concretetype = v.concretetype
     return newvar


From pedronis at codespeak.net  Sat May 13 23:42:54 2006
From: pedronis at codespeak.net (pedronis at codespeak.net)
Date: Sat, 13 May 2006 23:42:54 +0200 (CEST)
Subject: [pypy-svn] r27192 - in pypy/dist/pypy/jit/llabstractinterp: . test
Message-ID: <20060513214254.827BD100AA@code0.codespeak.net>

Author: pedronis
Date: Sat May 13 23:42:51 2006
New Revision: 27192

Modified:
   pypy/dist/pypy/jit/llabstractinterp/llvalue.py
   pypy/dist/pypy/jit/llabstractinterp/test/test_jit_tl.py
Log:
Void constants possible fix.



Modified: pypy/dist/pypy/jit/llabstractinterp/llvalue.py
==============================================================================
--- pypy/dist/pypy/jit/llabstractinterp/llvalue.py	(original)
+++ pypy/dist/pypy/jit/llabstractinterp/llvalue.py	Sat May 13 23:42:51 2006
@@ -16,6 +16,8 @@
         Hashable.__init__(self, value)   
         self.concretetype = T or lltype.typeOf(value)
         self.genvar = genvar
+        if T is lltype.Void and self.genvar is None:
+            self.genvar = rgenop.placeholder(value)
         
     def getgenvar(self, builder):
         if self.genvar is None:

Modified: pypy/dist/pypy/jit/llabstractinterp/test/test_jit_tl.py
==============================================================================
--- pypy/dist/pypy/jit/llabstractinterp/test/test_jit_tl.py	(original)
+++ pypy/dist/pypy/jit/llabstractinterp/test/test_jit_tl.py	Sat May 13 23:42:51 2006
@@ -9,8 +9,6 @@
 from pypy.jit.llabstractinterp.test.test_llabstractinterp import summary
 #from pypy.translator.backendopt import inline
 
-py.test.skip("not implementing: handling of Void values")
-
 def setup_module(mod):
     t = TranslationContext()
     t.buildannotator().build_types(tl.interp, [str, int])


From pedronis at codespeak.net  Sat May 13 23:52:00 2006
From: pedronis at codespeak.net (pedronis at codespeak.net)
Date: Sat, 13 May 2006 23:52:00 +0200 (CEST)
Subject: [pypy-svn] r27193 - pypy/dist/pypy/rpython/test
Message-ID: <20060513215200.A9BDE100AA@code0.codespeak.net>

Author: pedronis
Date: Sat May 13 23:51:59 2006
New Revision: 27193

Modified:
   pypy/dist/pypy/rpython/test/test_objectmodel.py
Log:
eh? stop-gap solution for  perplexingly broken check-in


Modified: pypy/dist/pypy/rpython/test/test_objectmodel.py
==============================================================================
--- pypy/dist/pypy/rpython/test/test_objectmodel.py	(original)
+++ pypy/dist/pypy/rpython/test/test_objectmodel.py	Sat May 13 23:51:59 2006
@@ -268,7 +268,7 @@
     assert A(12098).getvalue() == 12098
 
 def test_symbolic():
-    
+    py.test.skip("xxx no test here")
 
 def test_symbolic_raises():
     s1 = Symbolic()


From antocuni at codespeak.net  Sun May 14 10:53:30 2006
From: antocuni at codespeak.net (antocuni at codespeak.net)
Date: Sun, 14 May 2006 10:53:30 +0200 (CEST)
Subject: [pypy-svn] r27197 - in pypy/dist/pypy/rpython: ootypesystem
	ootypesystem/test test
Message-ID: <20060514085330.4E358100A9@code0.codespeak.net>

Author: antocuni
Date: Sun May 14 10:53:18 2006
New Revision: 27197

Modified:
   pypy/dist/pypy/rpython/ootypesystem/ootype.py
   pypy/dist/pypy/rpython/ootypesystem/rstr.py
   pypy/dist/pypy/rpython/ootypesystem/test/test_ooann.py
   pypy/dist/pypy/rpython/ootypesystem/test/test_oortype.py
   pypy/dist/pypy/rpython/test/test_rstr.py
Log:
More ootypesystem rstr test.



Modified: pypy/dist/pypy/rpython/ootypesystem/ootype.py
==============================================================================
--- pypy/dist/pypy/rpython/ootypesystem/ootype.py	(original)
+++ pypy/dist/pypy/rpython/ootypesystem/ootype.py	Sun May 14 10:53:18 2006
@@ -278,7 +278,10 @@
             "ll_stritem_nonneg": Meth([Signed], Char),
             "ll_strlen": Meth([], Signed),
             "ll_strconcat": Meth([self.SELFTYPE_T], self.SELFTYPE_T),
-            "ll_equal": Meth([self.SELFTYPE_T], Bool),
+            "ll_streq": Meth([self.SELFTYPE_T], Bool),
+            "ll_strcmp": Meth([self.SELFTYPE_T], Signed),
+            "ll_startswith": Meth([self.SELFTYPE_T], Bool),
+            "ll_endswith": Meth([self.SELFTYPE_T], Bool),            
         })
         self._setup_methods(generic_types)
 
@@ -808,10 +811,20 @@
         # NOT_RPYTHON
         return make_string(self._str + s._str)
 
-    def ll_equal(self, s):
+    def ll_streq(self, s):
         # NOT_RPYTON
         return self._str == s._str
 
+    def ll_strcmp(self, s):
+        # NOT_RPYTHON
+        return cmp(self._str, s._str)
+
+    def ll_startswith(self, s):
+        return self._str.startswith(s._str)
+
+    def ll_endswith(self, s):
+        return self._str.endswith(s._str)
+
     # delegate missing ll_* methods to self._str
     def __getattr__(self, attr):
         if attr.startswith('ll_'):
@@ -839,6 +852,7 @@
 class _null_string(_null_mixin(_string), _string):
     def __init__(self, STRING):
         self.__dict__["_TYPE"] = STRING
+        self.__dict__["_str"] = None
 
 class _string_builder(_builtin_type):
     def __init__(self, STRING_BUILDER):

Modified: pypy/dist/pypy/rpython/ootypesystem/rstr.py
==============================================================================
--- pypy/dist/pypy/rpython/ootypesystem/rstr.py	(original)
+++ pypy/dist/pypy/rpython/ootypesystem/rstr.py	Sun May 14 10:53:18 2006
@@ -75,7 +75,21 @@
     def ll_streq(s1, s2):
         if s1 is None:
             return s2 is None
-        return s1.ll_equal(s2)
+        return s1.ll_streq(s2)
+
+    def ll_strcmp(s1, s2):
+        if not s1 and not s2:
+            return True
+        if not s1 or not s2:
+            return False
+        return s1.ll_strcmp(s2)
+
+    def ll_startswith(s1, s2):
+        return s1.ll_startswith(s2)
+
+    def ll_endswith(s1, s2):
+        return s1.ll_endswith(s2)
+    
 
 string_repr = StringRepr()
 char_repr = CharRepr()

Modified: pypy/dist/pypy/rpython/ootypesystem/test/test_ooann.py
==============================================================================
--- pypy/dist/pypy/rpython/ootypesystem/test/test_ooann.py	(original)
+++ pypy/dist/pypy/rpython/ootypesystem/test/test_ooann.py	Sun May 14 10:53:18 2006
@@ -207,6 +207,17 @@
     s = a.build_types(oof, [])
     assert s == annmodel.SomeOOInstance(String)
 
+def test_nullstring():
+    def oof(b):
+        if b:
+            return 'foo'
+        else:
+            return None
+
+    a = RPythonAnnotator()
+    s = a.build_types(oof, [bool])
+    assert s == annmodel.SomeString(can_be_None=True)
+
 def test_oostring():
     def oof():
         return oostring

Modified: pypy/dist/pypy/rpython/ootypesystem/test/test_oortype.py
==============================================================================
--- pypy/dist/pypy/rpython/ootypesystem/test/test_oortype.py	(original)
+++ pypy/dist/pypy/rpython/ootypesystem/test/test_oortype.py	Sun May 14 10:53:18 2006
@@ -1,5 +1,6 @@
 from pypy import conftest
 from pypy.rpython.ootypesystem.ootype import *
+from pypy.rpython.ootypesystem import ootype
 from pypy.rpython.ootypesystem.rlist import ListRepr
 from pypy.rpython.rint import signed_repr
 from pypy.annotation import model as annmodel
@@ -203,3 +204,13 @@
     ch = 'a'
     res = interpret(oof, [ch], type_system='ootype')
     assert res._str == 'a'
+
+def test_nullstring():
+    def oof(b):
+        if b:
+            return 'foo'
+        else:
+            return None
+
+    res = interpret(oof, [False], type_system='ootype')
+    assert isinstance(res, ootype._null_string)

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 May 14 10:53:18 2006
@@ -145,102 +145,109 @@
         res = self.interpret(fn, ['5', 3])
         assert res == 5551
 
-def test_unichar_const():
-    def fn(c):
-        return c
-    assert interpret(fn, [u'\u03b1']) == u'\u03b1'
+    def test_unichar_const(self):
+        def fn(c):
+            return c
+        assert self.interpret(fn, [u'\u03b1']) == u'\u03b1'
+
+    def test_unichar_eq(self):
+        def fn(c1, c2):
+            return c1 == c2
+        assert self.interpret(fn, [u'\u03b1', u'\u03b1']) == True
+        assert self.interpret(fn, [u'\u03b1', u'\u03b2']) == False
+
+    def test_unichar_ord(self):
+        def fn(c):
+            return ord(c)
+        assert self.interpret(fn, [u'\u03b1']) == ord(u'\u03b1')
+
+    def test_unichar_hash(self):
+        def fn(c):
+            d = {c: 42}
+            return d[c]
+        assert self.interpret(fn, [u'\u03b1']) == 42
 
-def test_unichar_eq():
-    def fn(c1, c2):
-        return c1 == c2
-    assert interpret(fn, [u'\u03b1', u'\u03b1']) == True
-    assert interpret(fn, [u'\u03b1', u'\u03b2']) == False
-
-def test_unichar_ord():
-    def fn(c):
-        return ord(c)
-    assert interpret(fn, [u'\u03b1']) == ord(u'\u03b1')
-
-def test_unichar_hash():
-    def fn(c):
-        d = {c: 42}
-        return d[c]
-    assert interpret(fn, [u'\u03b1']) == 42
-
-def test_str_compare():
-    def fn(i, j):
-        s1 = ['one', 'two', None]
-        s2 = ['one', 'two', 'o', 'on', 'twos', 'foobar', None]
-        return s1[i] == s2[j]
-    for i in range(3):
-        for j in range(7):
-            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)
-
-    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)
-
-    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)
-
-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_is_none(self):
+        def fn(i):
+            s1 = ['foo', None][i]
+            return s1 is None
+        assert self.interpret(fn, [0]) == False
+        assert self.interpret(fn, [1]) == True
+
+    def test_str_compare(self):
+        def fn(i, j):
+            s1 = ['one', 'two', None]
+            s2 = ['one', 'two', 'o', 'on', 'twos', 'foobar', None]
+            return s1[i] == s2[j]
+        for i in range(3):
+            for j in range(7):
+                res = self.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 = self.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 = self.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 = self.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 = self.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 = self.interpret(fn, [i,j])
+                assert res is fn(i, j)
+
+    def test_startswith(self):
+        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 = self.interpret(fn, [i,j])
+                assert res is fn(i, j)
+
+    def test_endswith(self):
+        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 = self.interpret(fn, [i,j])
+                assert res is fn(i, j)
 
 def test_find():
     def fn(i, j):


From stephan at codespeak.net  Sun May 14 11:28:14 2006
From: stephan at codespeak.net (stephan at codespeak.net)
Date: Sun, 14 May 2006 11:28:14 +0200 (CEST)
Subject: [pypy-svn] r27198 - pypy/dist/pypy/module/stackless/test
Message-ID: <20060514092814.EEB7F100A9@code0.codespeak.net>

Author: stephan
Date: Sun May 14 11:28:12 2006
New Revision: 27198

Modified:
   pypy/dist/pypy/module/stackless/test/coro1.py   (props changed)
   pypy/dist/pypy/module/stackless/test/stack1.py   (props changed)
   pypy/dist/pypy/module/stackless/test/stack2.py   (props changed)
   pypy/dist/pypy/module/stackless/test/stack3.py   (props changed)
   pypy/dist/pypy/module/stackless/test/stackless_.py   (contents, props changed)
Log:
just set eol-style=native


Modified: pypy/dist/pypy/module/stackless/test/stackless_.py
==============================================================================
--- pypy/dist/pypy/module/stackless/test/stackless_.py	(original)
+++ pypy/dist/pypy/module/stackless/test/stackless_.py	Sun May 14 11:28:12 2006
@@ -11,13 +11,13 @@
 # interface from original stackless
 # class attributes are placeholders for some kind of descriptor
 # (to be filled in later).
-
-note = """
-The bomb object decouples exception creation and exception
-raising. This is necessary to support channels which don't
-immediately react on messages.
-
-This is a necessary Stackless 3.1 feature.
+
+note = """
+The bomb object decouples exception creation and exception
+raising. This is necessary to support channels which don't
+immediately react on messages.
+
+This is a necessary Stackless 3.1 feature.
 """
 class bomb(object):
     """
@@ -41,11 +41,11 @@
     traceback = None
     type = None
     value = None
-
-note = """
-cframes are an implementation detail.
-Do not implement this now. If we need such a thing in PyPy,
-then it will probably have a different layout.
+
+note = """
+cframes are an implementation detail.
+Do not implement this now. If we need such a thing in PyPy,
+then it will probably have a different layout.
 """
 class cframe(object):
     """
@@ -53,11 +53,11 @@
     __slots__ = ['f_back','obj1','obj2','obj3','i','n']
 
 # channel: see below
-
-note = """
-The future of C stacks is undecided, yet. This applies
-for Stackless, only at the moment. PyPy will use soft-switching
-only, until we support external callbacks.
+
+note = """
+The future of C stacks is undecided, yet. This applies
+for Stackless, only at the moment. PyPy will use soft-switching
+only, until we support external callbacks.
 """
 class cstack(object):
     """
@@ -66,10 +66,10 @@
     of program state. This structure is highly platform dependant.
     Note: For inspection, str() can dump it as a string.
     """
-
-note = """
-I would implement it as a simple flag but let it issue
-a warning that it has no effect.
+
+note = """
+I would implement it as a simple flag but let it issue
+a warning that it has no effect.
 """
 def enable_softswitch(flag):
     """
@@ -83,9 +83,9 @@
     By default, soft switching is enabled.
     """
     pass
-
-note = """
-Implementation can be deferred.
+
+note = """
+Implementation can be deferred.
 """
 def get_thread_info(thread_id):
     """
@@ -102,7 +102,7 @@
 # def run(timeout): see below
 
 # def schedule(retval=stackless.current) : see below
-
+
 note = 'needed'
 def schedule_remove(retval=None):
     """
@@ -112,9 +112,9 @@
     schedule_remove(retval=stackless.current) -- ditto, and remove self.
     """
     pass
-
-note = """
-should be implemented for debugging purposes. Low priority
+
+note = """
+should be implemented for debugging purposes. Low priority
 """
 def set_channel_callback(callable):
     """
@@ -128,8 +128,8 @@
     """
     pass
 
-note = """
-should be implemented for debugging purposes. Low priority
+note = """
+should be implemented for debugging purposes. Low priority
 """
 def set_schedule_callback(callable):
     """
@@ -143,12 +143,12 @@
     Pass None to switch monitoring off again.
     """
     pass
-
-note = """
-this was an experiment on deriving from a module.
-The idea was to make runcount and current into properties.
-__tasklet__ and __channel__ are also not used.
-It is ok to ignore these.
+
+note = """
+this was an experiment on deriving from a module.
+The idea was to make runcount and current into properties.
+__tasklet__ and __channel__ are also not used.
+It is ok to ignore these.
 """
 class slpmodule(object):
     """
@@ -161,7 +161,7 @@
     """
 
 # class tasklet: see below
-
+
 note = 'drop'
 def test_cframe(switches, words=0):
     """
@@ -222,11 +222,11 @@
     maintasklet = mt
     coro_reg[c] = mt
 
-note = """
-It is not needed to implement the watchdog feature right now.
-But run should be supported in the way the docstring says.
-The runner is always main, which must be removed while
-running all the tasklets. The implementation below is wrong.
+note = """
+It is not needed to implement the watchdog feature right now.
+But run should be supported in the way the docstring says.
+The runner is always main, which must be removed while
+running all the tasklets. The implementation below is wrong.
 """
 def run():
     """
@@ -240,12 +240,12 @@
     If an exception occours, it will be passed to the main tasklet.
     """
     schedule()
-
-note = """
-I don't see why coro_reg is needed.
-tasklets should ideally inherit from coroutine.
-This will create unwanted attributes, but they will
-go away when we port this to interp-leve.
+
+note = """
+I don't see why coro_reg is needed.
+tasklets should ideally inherit from coroutine.
+This will create unwanted attributes, but they will
+go away when we port this to interp-leve.
 """
 def getcurrent():
     """
@@ -277,32 +277,32 @@
 #    __slots__ = ['alive','atomic','block_trap','blocked','frame',
 #                 'ignore_nesting','is_current','is_main',
 #                 'nesting_level','next','paused','prev','recursion_depth',
-#                 'restorable','scheduled','thread_id']
-
-    ## note: most of the above should be properties
-
-    ## note that next and prev are not here.
-    ## should this be implemented, or better not?
-    ## I think yes. it is easier to keep the linkage.
-    ## tasklets gave grown this, and we can do different
-    ## classes, later.
-    ## well, it is a design question, but fow now probably simplest
+#                 'restorable','scheduled','thread_id']
+
+    ## note: most of the above should be properties
+
+    ## note that next and prev are not here.
+    ## should this be implemented, or better not?
+    ## I think yes. it is easier to keep the linkage.
+    ## tasklets gave grown this, and we can do different
+    ## classes, later.
+    ## well, it is a design question, but fow now probably simplest
     ## to just copy that.
 
-    def __init__(self, func=None):
+    def __init__(self, func=None):
         ## note: this field should reuse tempval to save space
         self._func = func
 
-    def __call__(self, *argl, **argd):
-        ## note: please inherit
-        ## note: please use spaces after comma :-)
+    def __call__(self, *argl, **argd):
+        ## note: please inherit
+        ## note: please use spaces after comma :-)
         ## note: please express this using bind and setup
         self._coro = c = coroutine()
         c.bind(self._func,*argl,**argd)
         coro_reg[c] = self
         self.insert()
         return self
-
+
     ## note: deprecated
     def become(self, retval=None):
         """
@@ -314,7 +314,7 @@
         If retval is not given, the tasklet is used as default.
         """
         pass
-
+
     ## note: __init__ should use this
     def bind(self):
         """
@@ -345,7 +345,7 @@
         Blocked tasklets need to be reactivated by channels.
         """
         scheduler.insert(self)
-
+
     ## note: this is needed. please call coroutine.kill()
     def kill(self):
         """
@@ -356,7 +356,7 @@
         the tasklet will silently die.
         """
         pass
-
+
     ## note: see the C implementation about how to use bombs
     def raise_exception(self, exc, value):
         """
@@ -382,12 +382,12 @@
         Run this tasklet, given that it isn't blocked.
         Blocked tasks need to be reactivated by channels.
         """
-        scheduler.setnexttask(self)
-        ## note: please support different schedulers
+        scheduler.setnexttask(self)
+        ## note: please support different schedulers
         ## and don't mix calls to module functions with scheduler methods.
         schedule()
-
-    ## note: needed at some point. right now just a property
+
+    ## note: needed at some point. right now just a property
     ## the stackless_flags should all be supported
     def set_atomic(self):
         """
@@ -405,7 +405,7 @@
         See set_ignore_nesting.
         """
         pass
-
+
     ## note: see above
     def set_ignore_nesting(self,flag):
         """
@@ -420,18 +420,18 @@
             t.set_ignore_nesting(tmp)
         """
         pass
-
-    ## note
-    ## tasklet(func)(*args, **kwds)
-    ## is identical to
+
+    ## note
+    ## tasklet(func)(*args, **kwds)
+    ## is identical to
     ## t = tasklet; t.bind(func); t.setup(*args, **kwds)
     def setup(self,*argl,**argd):
         """
         supply the parameters for the callable
         """
         pass
-
-    ## note: this attribute should always be there.
+
+    ## note: this attribute should always be there.
     ## no class default needed.
     tempval = None
 
@@ -448,11 +448,11 @@
 #                 'schedule_all']
 
     def __init__(self):
-        self.balance = 0
+        self.balance = 0
         ## note: this is a deque candidate.
         self._readq = []
         self._writeq = []
-
+
     ## note: needed
     def close(self):
         """
@@ -513,7 +513,7 @@
             nt, self._readq = self._readq[0], self._readq[1:]
             scheduler.priorityinsert(nt)
         schedule()
-
+
     ## note: see the C implementation on how to use bombs.
     def send_exception(self, exc, value):
         """
@@ -522,7 +522,7 @@
         Behavior is like channel.send, but that the receiver gets an exception.
         """
         pass
-
+
     ## needed
     def send_sequence(self, value):
         """
@@ -536,10 +536,10 @@
 
 
 class Scheduler(object):
-    def __init__(self):
+    def __init__(self):
         ## note: better use a deque
-        self.tasklist = []
-        ## note: in terms of moving to interplevel, I would not do that
+        self.tasklist = []
+        ## note: in terms of moving to interplevel, I would not do that
         self.nexttask = None 
 
     def empty(self):
@@ -588,9 +588,9 @@
     def setnexttask(self,task):
         if task not in self.tasklist:
             self.tasklist.insert(task)
-        try:
-            ## note: this is inefficient
-            ## please use the flag attributes
+        try:
+            ## note: this is inefficient
+            ## please use the flag attributes
             ## a tasklet 'knows' if it is in something
             i = self.tasklist.index(task)
             self.nexttask = i
@@ -602,6 +602,6 @@
 
 scheduler = Scheduler()
 __init()
-
-## note: nice work :-)
-
+
+## note: nice work :-)
+


From tismer at codespeak.net  Sun May 14 13:19:33 2006
From: tismer at codespeak.net (tismer at codespeak.net)
Date: Sun, 14 May 2006 13:19:33 +0200 (CEST)
Subject: [pypy-svn] r27199 - pypy/dist/pypy/translator/pickle
Message-ID: <20060514111933.6CC4610076@code0.codespeak.net>

Author: tismer
Date: Sun May 14 13:19:32 2006
New Revision: 27199

Modified:
   pypy/dist/pypy/translator/pickle/genpickle.py
Log:
revive genpickle a little bit by at least adapting to the new translationcontext

Modified: pypy/dist/pypy/translator/pickle/genpickle.py
==============================================================================
--- pypy/dist/pypy/translator/pickle/genpickle.py	(original)
+++ pypy/dist/pypy/translator/pickle/genpickle.py	Sun May 14 13:19:32 2006
@@ -372,14 +372,14 @@
                     #raise Exception, "unexpected name %r in class %s"%(key, cls)
                 if isapp:
                     if (isinstance(value, staticmethod) and value.__get__(1) not in
-                        self.translator.flowgraphs and self.translator.frozen):
+                        self.translator.flowgraphs and self.translator.annotator.frozen):
                         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):
+                        self.translator.flowgraphs and self.translator.annotator.frozen):
                         continue
                 if key in ignore:
                     continue
@@ -685,7 +685,7 @@
 
     def nameof_function(self, func):
         # look for skipped functions
-        if self.translator.frozen:
+        if self.translator.annotator.frozen:
             if func not in self.translator.flowgraphs:
                 # see if this is in translator's domain
                 module = whichmodule(func, func.__name__)


From arigo at codespeak.net  Sun May 14 13:29:33 2006
From: arigo at codespeak.net (arigo at codespeak.net)
Date: Sun, 14 May 2006 13:29:33 +0200 (CEST)
Subject: [pypy-svn] r27200 - in pypy/dist/pypy/rpython: . lltypesystem
Message-ID: <20060514112933.77AFC10092@code0.codespeak.net>

Author: arigo
Date: Sun May 14 13:29:32 2006
New Revision: 27200

Modified:
   pypy/dist/pypy/rpython/lltypesystem/rclass.py
   pypy/dist/pypy/rpython/rclass.py
Log:
Kill unused code.


Modified: pypy/dist/pypy/rpython/lltypesystem/rclass.py
==============================================================================
--- pypy/dist/pypy/rpython/lltypesystem/rclass.py	(original)
+++ pypy/dist/pypy/rpython/lltypesystem/rclass.py	Sun May 14 13:29:32 2006
@@ -8,8 +8,7 @@
                                 AbstractInstanceRepr,\
                                 MissingRTypeAttribute,\
                                 getclassrepr, getinstancerepr,\
-                                get_type_repr, rtype_new_instance,\
-                                instance_annotation_for_cls
+                                get_type_repr, rtype_new_instance
 from pypy.rpython.lltypesystem.lltype import \
      ForwardReference, GcForwardReference, \
      Ptr, Struct, GcStruct, malloc, \

Modified: pypy/dist/pypy/rpython/rclass.py
==============================================================================
--- pypy/dist/pypy/rpython/rclass.py	(original)
+++ pypy/dist/pypy/rpython/rclass.py	Sun May 14 13:29:32 2006
@@ -193,10 +193,3 @@
 def rtype_new_instance(rtyper, classdef, llops, classcallhop=None):
     rinstance = getinstancerepr(rtyper, classdef)
     return rinstance.new_instance(llops, classcallhop)
-
-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)


From arigo at codespeak.net  Sun May 14 13:31:34 2006
From: arigo at codespeak.net (arigo at codespeak.net)
Date: Sun, 14 May 2006 13:31:34 +0200 (CEST)
Subject: [pypy-svn] r27201 - pypy/dist/pypy/translator
Message-ID: <20060514113134.9981310092@code0.codespeak.net>

Author: arigo
Date: Sun May 14 13:31:33 2006
New Revision: 27201

Modified:
   pypy/dist/pypy/translator/geninterplevel.py
Log:
Kill unused code.


Modified: pypy/dist/pypy/translator/geninterplevel.py
==============================================================================
--- pypy/dist/pypy/translator/geninterplevel.py	(original)
+++ pypy/dist/pypy/translator/geninterplevel.py	Sun May 14 13:31:33 2006
@@ -631,17 +631,11 @@
     nameof_method = nameof_instancemethod   # when run on top of PyPy
 
     def should_translate_attr(self, pbc, attr):
-        ann = self.translator.annotator
-        if ann is None:
-            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
+        ignore = getattr(pbc.__class__, 'NOT_RPYTHON_ATTRIBUTES', [])
+        if attr in ignore:
+            return False
+        else:
+            return "probably"   # True
 
     def later(self, gen):
         self.latercode.append1((gen, self.debugstack))


From arigo at codespeak.net  Sun May 14 13:52:40 2006
From: arigo at codespeak.net (arigo at codespeak.net)
Date: Sun, 14 May 2006 13:52:40 +0200 (CEST)
Subject: [pypy-svn] r27202 - pypy/dist/pypy/translator/java
	user/arigo/hack/pypy-hack/java
Message-ID: <20060514115240.18E4F100B8@code0.codespeak.net>

Author: arigo
Date: Sun May 14 13:52:37 2006
New Revision: 27202

Added:
   user/arigo/hack/pypy-hack/java/
      - copied from r27201, pypy/dist/pypy/translator/java/
Removed:
   pypy/dist/pypy/translator/java/
Log:
Move the old, not-the-right-direction genjava into my 'pypy-hack' area.



From arigo at codespeak.net  Sun May 14 13:58:07 2006
From: arigo at codespeak.net (arigo at codespeak.net)
Date: Sun, 14 May 2006 13:58:07 +0200 (CEST)
Subject: [pypy-svn] r27203 - pypy/dist/pypy/doc
Message-ID: <20060514115807.0F4EB10092@code0.codespeak.net>

Author: arigo
Date: Sun May 14 13:58:05 2006
New Revision: 27203

Modified:
   pypy/dist/pypy/doc/translation.txt
Log:
Fix and update the list of our back-ends.


Modified: pypy/dist/pypy/doc/translation.txt
==============================================================================
--- pypy/dist/pypy/doc/translation.txt	(original)
+++ pypy/dist/pypy/doc/translation.txt	Sun May 14 13:58:05 2006
@@ -44,9 +44,9 @@
 
 5. One of the Code Generators (back-ends) turns the
    optionally annotated/typed flow graphs and produces a source file in
-   a lower-level language: C_, LLVM_, `Common Lisp`_, Pyrex_, Java_, or
-   `Python again`_ (this is used in PyPy to turn sufficiently RPythonic
-   app-level code into interp-level code).
+   a lower-level language: C_, LLVM_, `Common Lisp`_, Pyrex_, JavaScript_,
+   Squeak_, CLI_ (.NET), or `Python again`_ (this is used in PyPy to turn
+   sufficiently RPythonic app-level code into interp-level code).
 
 6. This lower-level source file is compiled to produce an executable.
 
@@ -55,9 +55,11 @@
 .. _`play around`: getting-started.html#trying-out-the-translator
 .. _`Flow Object Space`: objspace.html#the-flow-object-space
 .. _`control flow graph`: objspace.html#the-flow-model
-.. _`Common Lisp`: http://codespeak.net/pypy/dist/pypy/translator/gencl.py
-.. _Pyrex: http://codespeak.net/pypy/dist/pypy/translator/pyrex/genpyrex.py
-.. _Java: http://codespeak.net/pypy/dist/pypy/translator/java/
+.. _`Common Lisp`: http://codespeak.net/pypy/dist/pypy/translator/cl/
+.. _Pyrex: http://codespeak.net/pypy/dist/pypy/translator/pyrex/
+.. _JavaScript: http://codespeak.net/pypy/dist/pypy/translator/js/
+.. _Squeak: http://codespeak.net/pypy/dist/pypy/translator/squeak/
+.. _CLI: http://codespeak.net/pypy/dist/pypy/translator/cli/
 .. _graph: image/translation.pdf
 
 


From arigo at codespeak.net  Sun May 14 16:52:50 2006
From: arigo at codespeak.net (arigo at codespeak.net)
Date: Sun, 14 May 2006 16:52:50 +0200 (CEST)
Subject: [pypy-svn] r27204 - in pypy/dist/pypy: rpython rpython/lltypesystem
	rpython/memory translator/c translator/c/test translator/stackless
Message-ID: <20060514145250.C895F10092@code0.codespeak.net>

Author: arigo
Date: Sun May 14 16:52:46 2006
New Revision: 27204

Modified:
   pypy/dist/pypy/rpython/annlowlevel.py
   pypy/dist/pypy/rpython/lltypesystem/lloperation.py
   pypy/dist/pypy/rpython/memory/gc.py
   pypy/dist/pypy/rpython/memory/gctransform.py
   pypy/dist/pypy/translator/c/genc.py
   pypy/dist/pypy/translator/c/test/test_newgc.py
   pypy/dist/pypy/translator/c/test/test_stackless.py
   pypy/dist/pypy/translator/stackless/transform.py
Log:
(pedronis, arigo)
General progress towards stackless_gc.  Introduced malloc(flavor='gc_nocollect')
that doesn't trigger a collect.

Worth to note: genc now makes a Makefile with a 'debug:' entry, which
cleans up and recompiles in debug mode.



Modified: pypy/dist/pypy/rpython/annlowlevel.py
==============================================================================
--- pypy/dist/pypy/rpython/annlowlevel.py	(original)
+++ pypy/dist/pypy/rpython/annlowlevel.py	Sun May 14 16:52:46 2006
@@ -138,13 +138,20 @@
         # get a delayed pointer to the low-level function, annotated as
         # specified.  The pointer is only valid after finish() was called.
         graph = self.getgraph(ll_function, args_s, s_result)
+        return self.graph2delayed(graph)
+
+    def constfunc(self, ll_function, args_s, s_result):
+        p = self.delayedfunction(ll_function, args_s, s_result)
+        return Constant(p, lltype.typeOf(p))
+
+    def graph2delayed(self, graph):
         FUNCTYPE = lltype.ForwardReference()
         delayedptr = lltype._ptr(lltype.Ptr(FUNCTYPE), "delayed!", solid=True)
         self.delayedfuncs.append((delayedptr, graph))
         return delayedptr
 
-    def constfunc(self, ll_function, args_s, s_result):
-        p = self.delayedfunction(ll_function, args_s, s_result)
+    def graph2const(self, graph):
+        p = self.graph2delayed(graph)
         return Constant(p, lltype.typeOf(p))
 
     def getdelayedrepr(self, s_value):

Modified: pypy/dist/pypy/rpython/lltypesystem/lloperation.py
==============================================================================
--- pypy/dist/pypy/rpython/lltypesystem/lloperation.py	(original)
+++ pypy/dist/pypy/rpython/lltypesystem/lloperation.py	Sun May 14 16:52:46 2006
@@ -304,7 +304,7 @@
 
     # __________ GC operations __________
 
-    'gc__collect':          LLOp(),
+    'gc__collect':          LLOp(canraise=(Exception,)),
     'gc_free':              LLOp(),
     'gc_fetch_exception':   LLOp(),
     'gc_restore_exception': LLOp(),

Modified: pypy/dist/pypy/rpython/memory/gc.py
==============================================================================
--- pypy/dist/pypy/rpython/memory/gc.py	(original)
+++ pypy/dist/pypy/rpython/memory/gc.py	Sun May 14 16:52:46 2006
@@ -140,11 +140,12 @@
         if self.is_varsize(typeid):
             itemsize = self.varsize_item_sizes(typeid)
             offset_to_length = self.varsize_offset_to_length(typeid)
-            return self.malloc_varsize(typeid, length, size, itemsize, offset_to_length)
-        return self.malloc_fixedsize(typeid, size)
+            return self.malloc_varsize(typeid, length, size, itemsize,
+                                       offset_to_length, True)
+        return self.malloc_fixedsize(typeid, size, True)
 
-    def malloc_fixedsize(self, typeid, size):
-        if self.bytes_malloced > self.heap_size:
+    def malloc_fixedsize(self, typeid, size, can_collect):
+        if can_collect and self.bytes_malloced > self.heap_size:
             self.collect()
         size_gc_header = MarkSweepGC._size_gc_header
         result = raw_malloc(size + size_gc_header)
@@ -152,9 +153,10 @@
         self.malloced_objects.append(result)
         self.bytes_malloced += size + size_gc_header
         return result + size_gc_header
-         
-    def malloc_varsize(self, typeid, length, size, itemsize, offset_to_length):
-        if self.bytes_malloced > self.heap_size:
+
+    def malloc_varsize(self, typeid, length, size, itemsize, offset_to_length,
+                       can_collect):
+        if can_collect and self.bytes_malloced > self.heap_size:
             self.collect()
         try:
             varsize = rarithmetic.ovfcheck(length * itemsize)
@@ -242,6 +244,8 @@
         self.malloced_objects = newmo
         if curr_heap_size > self.heap_size:
             self.heap_size = curr_heap_size
+        # warning, the following debug print allocates memory to manipulate
+        # the strings!  so it must be at the end
         os.write(2, "freed %s bytes. the heap is now %s bytes.\n" % (freed_size, curr_heap_size))
 
     def size_gc_header(self, typeid=0):

Modified: pypy/dist/pypy/rpython/memory/gctransform.py
==============================================================================
--- pypy/dist/pypy/rpython/memory/gctransform.py	(original)
+++ pypy/dist/pypy/rpython/memory/gctransform.py	Sun May 14 16:52:46 2006
@@ -44,6 +44,10 @@
         if inline:
             self.lltype_to_classdef = translator.rtyper.lltype_to_classdef_mapping()
         self.graphs_to_inline = {}
+        if self.MinimalGCTransformer:
+            self.minimalgctransformer = self.MinimalGCTransformer(self)
+        else:
+            self.minimalgctransformer = None
 
     def get_lltype_of_exception_value(self):
         if self.translator is not None:
@@ -62,7 +66,8 @@
 
     def transform_graph(self, graph):
         if graph in self.minimal_transform:
-            MinimalGCTransformer(self.translator).transform_graph(graph)
+            if self.minimalgctransformer:
+                self.minimalgctransformer.transform_graph(graph)
             del self.minimal_transform[graph]
             return
         if graph in self.seen_graphs:
@@ -281,12 +286,18 @@
             self.mixlevelannotator.finish_rtype()
 
 class MinimalGCTransformer(GCTransformer):
+    def __init__(self, parenttransformer):
+        GCTransformer.__init__(self, parenttransformer.translator)
+        self.parenttransformer = parenttransformer
+
     def push_alive(self, var):
         return []
 
     def pop_alive(self, var):
         return []
 
+GCTransformer.MinimalGCTransformer = MinimalGCTransformer
+MinimalGCTransformer.MinimalGCTransformer = None
 
 # ----------------------------------------------------------------
 
@@ -586,12 +597,6 @@
     var.concretetype = concretetype
     return var
 
-def const_funcptr_fromgraph(graph):
-    FUNC = lltype.FuncType([v.concretetype for v in graph.startblock.inputargs],
-                           graph.returnblock.inputargs[0].concretetype)
-    return rmodel.inputconst(lltype.Ptr(FUNC),
-                             typesystem.getfunctionptr(graph))
-
 def find_gc_ptrs_in_type(TYPE):
     if isinstance(TYPE, lltype.Array):
         return find_gc_ptrs_in_type(TYPE.OF)
@@ -724,6 +729,7 @@
 
 class FrameworkGCTransformer(GCTransformer):
     use_stackless = False
+    extra_static_slots = 0
 
     def __init__(self, translator):
         from pypy.rpython.memory.support import get_address_linked_list
@@ -824,51 +830,53 @@
             annmodel.SomeAddress())
         
         annhelper = annlowlevel.MixLevelHelperAnnotator(self.translator.rtyper)
-        frameworkgc_setup_graph = annhelper.getgraph(frameworkgc_setup, [],
-                                                     annmodel.s_None)
+
+        def getfn(ll_function, args_s, s_result, inline=False):
+            graph = annhelper.getgraph(ll_function, args_s, s_result)
+            self.need_minimal_transform(graph)
+            if inline:
+                self.graphs_to_inline[graph] = True
+            return annhelper.graph2const(graph)
+
+        self.frameworkgc_setup_ptr = getfn(frameworkgc_setup, [],
+                                           annmodel.s_None)
         if StackRootIterator.push_root is None:
-            push_root_graph = None
+            self.push_root_ptr = None
         else:
-            push_root_graph = annhelper.getgraph(StackRootIterator.push_root,
-                                                 [annmodel.SomeAddress()],
-                                                 annmodel.s_None)
+            self.push_root_ptr = getfn(StackRootIterator.push_root,
+                                       [annmodel.SomeAddress()],
+                                       annmodel.s_None,
+                                       inline = True)
         if StackRootIterator.pop_root is None:
-            pop_root_graph = None
+            self.pop_root_ptr = None
         else:
-            pop_root_graph = annhelper.getgraph(StackRootIterator.pop_root, [],
-                                                annmodel.s_None)
+            self.pop_root_ptr = getfn(StackRootIterator.pop_root, [],
+                                      annmodel.s_None,
+                                      inline = True)
 
         classdef = bk.getuniqueclassdef(GCData.GCClass)
         s_gcdata = annmodel.SomeInstance(classdef)
-        malloc_fixedsize_graph = annhelper.getgraph(
+        self.malloc_fixedsize_ptr = getfn(
             GCData.GCClass.malloc_fixedsize.im_func,
             [s_gcdata, annmodel.SomeInteger(nonneg=True),
-             annmodel.SomeInteger(nonneg=True)], annmodel.SomeAddress())
-        malloc_varsize_graph = annhelper.getgraph(
+             annmodel.SomeInteger(nonneg=True),
+             annmodel.SomeBool()], annmodel.SomeAddress(),
+            inline = True)
+        self.malloc_varsize_ptr = getfn(
             GCData.GCClass.malloc_varsize.im_func,
-            [s_gcdata] + [annmodel.SomeInteger(nonneg=True) for i in range(5)],
-            annmodel.SomeAddress())
-        collect_graph = annhelper.getgraph(GCData.GCClass.collect.im_func,
+            [s_gcdata] + [annmodel.SomeInteger(nonneg=True) for i in range(5)]
+            + [annmodel.SomeBool()], annmodel.SomeAddress())
+        self.collect_ptr = getfn(GCData.GCClass.collect.im_func,
             [s_gcdata], annmodel.s_None)
         annhelper.finish()   # at this point, annotate all mix-level helpers
-        self.frameworkgc_setup_ptr = self.graph2funcptr(frameworkgc_setup_graph)
-        if push_root_graph is None:
-            self.push_root_ptr = None
-        else:
-            self.push_root_ptr = self.graph2funcptr(push_root_graph)
-            self.graphs_to_inline[push_root_graph] = True
-        if pop_root_graph is None:
-            self.pop_root_ptr = None
-        else:
-            self.pop_root_ptr = self.graph2funcptr(pop_root_graph)
-            self.graphs_to_inline[pop_root_graph] = True
-        self.malloc_fixedsize_ptr = self.graph2funcptr(malloc_fixedsize_graph)
-        self.malloc_varsize_ptr = self.graph2funcptr(malloc_varsize_graph)
-        self.collect_ptr = self.graph2funcptr(collect_graph)
-        self.graphs_to_inline[malloc_fixedsize_graph] = True
+
         self.collect_analyzer = CollectAnalyzer(self.translator)
         self.collect_analyzer.analyze_all()
 
+        s_gc = self.translator.annotator.bookkeeper.valueoftype(self.gcdata.GCClass)
+        r_gc = self.translator.rtyper.getrepr(s_gc)
+        self.c_const_gc = rmodel.inputconst(r_gc, self.gcdata.gc)
+
     def build_stack_root_iterator(self):
         rootstacksize = 640*1024    # XXX adjust
         gcdata = self.gcdata
@@ -914,10 +922,6 @@
 
         return StackRootIterator
 
-    def graph2funcptr(self, graph):
-        self.need_minimal_transform(graph)
-        return const_funcptr_fromgraph(graph)
-
     def get_type_id(self, TYPE):
         try:
             return self.id_of_type[TYPE]
@@ -1017,7 +1021,8 @@
             #self.gcdata.type_info_table = table
 
             ll_static_roots = lltype.malloc(lltype.Array(llmemory.Address),
-                                            len(self.static_gc_roots),
+                                            len(self.static_gc_roots) +
+                                                self.extra_static_slots,
                                             immortal=True)
             for i in range(len(self.static_gc_roots)):
                 c = self.static_gc_roots[i]
@@ -1055,7 +1060,17 @@
     replace_indirect_call  = replace_direct_call
 
     def replace_malloc(self, op, livevars, block):
-        TYPE = op.args[0].value
+        if op.opname.startswith('flavored_'):
+            flavor = op.args[0].value
+            TYPE = op.args[1].value
+        else:
+            flavor = 'gc'
+            TYPE = op.args[0].value
+
+        if not flavor.startswith('gc'):
+            return [op], 0
+        c_can_collect = rmodel.inputconst(lltype.Bool,
+                                          flavor != 'gc_nocollect')
         PTRTYPE = op.result.concretetype
         assert PTRTYPE.TO == TYPE
         type_id = self.get_type_id(TYPE)
@@ -1064,20 +1079,16 @@
         c_type_id = rmodel.inputconst(lltype.Signed, type_id)
         info = self.type_info_list[type_id]
         c_size = rmodel.inputconst(lltype.Signed, info["fixedsize"])
-
-        # surely there's a better way of doing this?
-        s_gc = self.translator.annotator.bookkeeper.valueoftype(self.gcdata.GCClass)
-        r_gc = self.translator.rtyper.getrepr(s_gc)
-        const_gc = rmodel.inputconst(r_gc, self.gcdata.gc)
-        if len(op.args) == 1:
-            args = [self.malloc_fixedsize_ptr, const_gc, c_type_id,
-                    c_size]
+        if not op.opname.endswith('_varsize'):
+            args = [self.malloc_fixedsize_ptr, self.c_const_gc, c_type_id,
+                    c_size, c_can_collect]
         else:
-            v_length = op.args[1]
+            v_length = op.args[-1]
             c_ofstolength = rmodel.inputconst(lltype.Signed, info['ofstolength'])
             c_varitemsize = rmodel.inputconst(lltype.Signed, info['varitemsize'])
-            args = [self.malloc_varsize_ptr, const_gc, c_type_id,
-                    v_length, c_size, c_varitemsize, c_ofstolength] 
+            args = [self.malloc_varsize_ptr, self.c_const_gc, c_type_id,
+                    v_length, c_size, c_varitemsize, c_ofstolength,
+                    c_can_collect]
         newop = SpaceOperation("direct_call", args, v)
         ops, index = self.protect_roots(newop, livevars, block,
                                         block.operations.index(op))
@@ -1085,14 +1096,14 @@
         return ops
 
     replace_malloc_varsize = replace_malloc
+    replace_flavored_malloc = replace_malloc
+    replace_flavored_malloc_varsize = replace_malloc
 
     def replace_gc__collect(self, op, livevars, block):
-        # surely there's a better way of doing this?
-        s_gc = self.translator.annotator.bookkeeper.valueoftype(self.gcdata.GCClass)
-        r_gc = self.translator.rtyper.getrepr(s_gc)
-        const_gc = rmodel.inputconst(r_gc, self.gcdata.gc)
         newop = SpaceOperation(
-                    "direct_call", [self.collect_ptr, const_gc], op.result)
+                    "direct_call",
+                    [self.collect_ptr, self.c_const_gc],
+                    op.result)
         ops, index = self.protect_roots(newop, livevars, block,
                                         block.operations.index(op))
         return ops
@@ -1147,9 +1158,25 @@
         offsets.append(0)
     return offsets
 
+# ____________________________________________________________
+
+
+class StacklessFrameworkMinimalGCTransformer(MinimalGCTransformer):
+    def replace_flavored_malloc(self, op, livevars, block):
+        flavor = op.args[0].value
+        if flavor == 'gc_nocollect':
+            return self.parenttransformer.replace_flavored_malloc(op,
+                                                                  livevars,
+                                                                  block)
+        else:
+            return [op], 0
+    replace_flavored_malloc_varsize = replace_flavored_malloc
+
 
 class StacklessFrameworkGCTransformer(FrameworkGCTransformer):
     use_stackless = True
+    extra_static_slots = 1     # for the stack_capture()'d frame
+    MinimalGCTransformer = StacklessFrameworkMinimalGCTransformer
 
     def build_stack_root_iterator(self):
         from pypy.rpython.rstack import stack_capture
@@ -1167,9 +1194,11 @@
             pop_root = None
 
             def __init__(self):
-                self.provide_current_frame = True
+                frame = llmemory.cast_ptr_to_adr(stack_capture())
                 self.static_current = gcdata.static_root_start
-                self.static_roots_index = len(gcdata.static_roots)
+                index = len(gcdata.static_roots)
+                self.static_roots_index = index
+                gcdata.static_roots[index-1] = frame
 
             def pop(self):
                 while self.static_current != gcdata.static_root_end:
@@ -1181,11 +1210,9 @@
                 if i > 0:
                     i -= 1
                     self.static_roots_index = i
-                    return gcdata.static_roots[i]
-                if self.provide_current_frame:
-                    self.provide_current_frame = False
-                    frame = stack_capture()
-                    return llmemory.cast_ptr_to_adr(frame)
+                    p = lltype.direct_arrayitems(gcdata.static_roots)
+                    p = lltype.direct_ptradd(p, i)
+                    return llmemory.cast_ptr_to_adr(p)
                 return llmemory.NULL
 
         return StackRootIterator

Modified: pypy/dist/pypy/translator/c/genc.py
==============================================================================
--- pypy/dist/pypy/translator/c/genc.py	(original)
+++ pypy/dist/pypy/translator/c/genc.py	Sun May 14 16:52:46 2006
@@ -783,4 +783,7 @@
 
 clean:
 \trm -f $(OBJECTS) $(TARGET)
+
+debug: clean
+\tmake CFLAGS="-g -pthread"
 '''

Modified: pypy/dist/pypy/translator/c/test/test_newgc.py
==============================================================================
--- pypy/dist/pypy/translator/c/test/test_newgc.py	(original)
+++ pypy/dist/pypy/translator/c/test/test_newgc.py	Sun May 14 16:52:46 2006
@@ -570,6 +570,7 @@
         runner.gcpolicy = self.gcpolicy
         runner.stacklessmode = True
         res = runner.wrap_stackless_function(f)
+        self.t = runner.t
         def compiled():
             return res
         return compiled

Modified: pypy/dist/pypy/translator/c/test/test_stackless.py
==============================================================================
--- pypy/dist/pypy/translator/c/test/test_stackless.py	(original)
+++ pypy/dist/pypy/translator/c/test/test_stackless.py	Sun May 14 16:52:46 2006
@@ -35,6 +35,7 @@
         s_list_of_strings = SomeList(ListDef(None, SomeString()))
         s_list_of_strings.listdef.resize()
         t = TranslationContext()
+        self.t = t
         t.buildannotator().build_types(entry_point, [s_list_of_strings])
         t.buildrtyper().specialize()
         if self.backendopt:

Modified: pypy/dist/pypy/translator/stackless/transform.py
==============================================================================
--- pypy/dist/pypy/translator/stackless/transform.py	(original)
+++ pypy/dist/pypy/translator/stackless/transform.py	Sun May 14 16:52:46 2006
@@ -33,7 +33,7 @@
 #         try:
 #             retval = g(x)
 #         except code.UnwindException, u:
-#             state = lltype.malloc(STATE_func_0)
+#             state = lltype.malloc(STATE_func_0, flavor='gc_nocollect')
 #             state.header.f_restart = 
 #             state.saved_long_0 = x
 #             code.add_frame_state(u, state.header)
@@ -98,7 +98,8 @@
 
     def operation_is_true(self, op):
         return (op.opname == 'yield_current_frame_to_caller' or
-                op.opname.startswith('malloc') and self.stackless_gc)
+                self.stackless_gc and (op.opname.startswith('malloc')
+                                       or op.opname == 'gc__collect'))
 
     def analyze_link(self, graph, link):
         if link.target is graph.exceptblock:
@@ -121,6 +122,7 @@
 
     def __init__(self, translator, entrypoint, stackless_gc=False):
         self.translator = translator
+        self.stackless_gc = stackless_gc
 
         self.frametyper = FrameTyper()
         self.masterarray1 = []
@@ -221,6 +223,7 @@
         self.c_minus_one = model.Constant(-1, lltype.Signed)
         self.c_null_state = model.Constant(null_state,
                                            lltype.typeOf(null_state))
+        self.c_gc_nocollect = model.Constant("gc_nocollect", lltype.Void)
 
         # register the prebuilt restartinfos
         for restartinfo in frame.RestartInfo.prebuilt:
@@ -236,6 +239,8 @@
         
         if hasattr(graph, 'func'):
             if getattr(graph.func, 'stackless_explicit', False):
+                if self.stackless_gc:
+                    self.transform_gc_nocollect(graph)
                 return
 
         if not self.analyzer.analyze_direct_call(graph):
@@ -396,8 +401,8 @@
                 op = replace_with_call(self.yield_current_frame_to_caller_ptr)
                 stackless_op = True
                 
-            if (op.opname in ('direct_call', 'indirect_call') or
-                op.opname.startswith('malloc')):
+            if (op.opname in ('direct_call', 'indirect_call')
+                or self.analyzer.operation_is_true(op)):
                 # trap calls to stackless-related suggested primitives
                 if op.opname == 'direct_call':
                     func = getattr(op.args[0].value._obj, '_callable', None)
@@ -495,11 +500,17 @@
         saveops = save_state_block.operations
         frame_state_var = varoftype(lltype.Ptr(frame_type))
 
-        saveops.append(model.SpaceOperation(
-            'malloc',
-            [model.Constant(frame_type, lltype.Void)],
-            frame_state_var))
-        
+        if self.stackless_gc:
+            saveops.append(model.SpaceOperation(
+                'flavored_malloc',
+                [self.c_gc_nocollect, model.Constant(frame_type, lltype.Void)],
+                frame_state_var))
+        else:
+            saveops.append(model.SpaceOperation(
+                'malloc',
+                [model.Constant(frame_type, lltype.Void)],
+                frame_state_var))
+
         saveops.extend(self.generate_saveops(frame_state_var, inputargs,
                                              fieldnames))
 
@@ -576,3 +587,14 @@
         ll_global_state = self.ll_global_state.value
         ll_global_state.inst_masterarray = masterarray
         return [masterarray]
+
+    def transform_gc_nocollect(self, graph):
+        # for the framework gc: in stackless_explicit graphs, make sure
+        # that the mallocs won't trigger a collect.
+        for block in graph.iterblocks():
+            for i, op in enumerate(block.operations):
+                if op.opname.startswith('malloc'):
+                    newop = model.SpaceOperation('flavored_' + op.opname,
+                                                 [self.c_gc_nocollect]+op.args,
+                                                 op.result)
+                    block.operations[i] = newop


From arigo at codespeak.net  Sun May 14 17:37:42 2006
From: arigo at codespeak.net (arigo at codespeak.net)
Date: Sun, 14 May 2006 17:37:42 +0200 (CEST)
Subject: [pypy-svn] r27205 - in pypy/dist/pypy: annotation
	rpython/memory/test translator translator/backendopt/test
	translator/c translator/c/test translator/goal
	translator/llvm/demo translator/stackless/test
Message-ID: <20060514153742.0A3F110093@code0.codespeak.net>

Author: arigo
Date: Sun May 14 17:37:36 2006
New Revision: 27205

Modified:
   pypy/dist/pypy/annotation/listdef.py
   pypy/dist/pypy/rpython/memory/test/test_gctransform.py
   pypy/dist/pypy/translator/backendopt/test/test_all.py
   pypy/dist/pypy/translator/c/database.py
   pypy/dist/pypy/translator/c/funcgen.py
   pypy/dist/pypy/translator/c/genc.py
   pypy/dist/pypy/translator/c/node.py
   pypy/dist/pypy/translator/c/test/test_stackless.py
   pypy/dist/pypy/translator/c/test/test_standalone.py
   pypy/dist/pypy/translator/driver.py
   pypy/dist/pypy/translator/goal/targetlogic.py
   pypy/dist/pypy/translator/goal/targetlogicstandalone.py
   pypy/dist/pypy/translator/goal/targetmultiplespaces.py
   pypy/dist/pypy/translator/goal/targetpypy_stacklesstest.py
   pypy/dist/pypy/translator/goal/targetpypymain.py
   pypy/dist/pypy/translator/goal/targetpypystandalone.py
   pypy/dist/pypy/translator/goal/targetthunkstandalone.py
   pypy/dist/pypy/translator/llvm/demo/run.py
   pypy/dist/pypy/translator/stackless/test/test_transform.py
Log:
(pedronis, arigo)
* started a test for the gctransformer on top of the llinterp.
* regrouped the numerous s_list_of_strings into listdef.
* added an interface in genc to prepare the database and the
    graphs without actually emitting source.
* clean-up in node about 'isgchelper', which is a name that
    used to be possibly confused for the name of a field in a
    GcStruct (!).


Modified: pypy/dist/pypy/annotation/listdef.py
==============================================================================
--- pypy/dist/pypy/annotation/listdef.py	(original)
+++ pypy/dist/pypy/annotation/listdef.py	Sun May 14 17:37:36 2006
@@ -1,4 +1,5 @@
 from pypy.annotation.model import SomeObject, SomeImpossibleValue
+from pypy.annotation.model import SomeList, SomeString
 from pypy.annotation.model import unionof, TLS, UnionError, isdegenerated
 
 
@@ -135,3 +136,6 @@
 
 
 MOST_GENERAL_LISTDEF = ListDef(None, SomeObject())
+
+s_list_of_strings = SomeList(ListDef(None, SomeString()))
+s_list_of_strings.listdef.resize()

Modified: pypy/dist/pypy/rpython/memory/test/test_gctransform.py
==============================================================================
--- pypy/dist/pypy/rpython/memory/test/test_gctransform.py	(original)
+++ pypy/dist/pypy/rpython/memory/test/test_gctransform.py	Sun May 14 17:37:36 2006
@@ -684,14 +684,32 @@
 # ______________________________________________________________________
 # tests for FrameworkGCTransformer
 
-def DONT_test_framework_simple():
+def test_framework_simple():
     def g(x):
         return x + 1
     class A(object):
         pass
-    def f():
+    def entrypoint(argv):
         a = A()
         a.b = g(1)
-        return a.b
-    t, transformer = rtype_and_transform(f, [], gctransform.FrameworkGCTransformer, check=False)
-    # assert did not crash :-/
+        return str(a.b)
+
+    from pypy.rpython.llinterp import LLInterpreter
+    from pypy.translator.c.genc import CStandaloneBuilder
+    from pypy.translator.c import gc
+    from pypy.annotation.listdef import s_list_of_strings
+    
+    t = rtype(entrypoint, [s_list_of_strings])
+    cbuild = CStandaloneBuilder(t, entrypoint, gc.FrameworkGcPolicy)
+    cbuild.generate_graphs_for_llinterp()
+    entrypointptr = cbuild.getentrypointptr()
+    entrygraph = entrypointptr._obj.graph
+
+    r_list_of_strings = t.rtyper.getrepr(s_list_of_strings)
+    ll_argv = r_list_of_strings.convert_const([])
+
+    py.test.skip('in-progress')
+    llinterp = LLInterpreter(t.rtyper)
+    res = llinterp.eval_graph(entrygraph, [ll_argv])
+
+    assert ''.join(res.chars) == "2"

Modified: pypy/dist/pypy/translator/backendopt/test/test_all.py
==============================================================================
--- pypy/dist/pypy/translator/backendopt/test/test_all.py	(original)
+++ pypy/dist/pypy/translator/backendopt/test/test_all.py	Sun May 14 17:37:36 2006
@@ -92,10 +92,9 @@
 
 def test_premature_death():
     import os
-    from pypy.annotation import listdef
+    from pypy.annotation.listdef import s_list_of_strings
 
-    ldef = listdef.ListDef(None, annmodel.SomeString())
-    inputtypes = [annmodel.SomeList(ldef)]
+    inputtypes = [s_list_of_strings]
 
     def debug(msg): 
         os.write(2, "debug: " + msg + '\n')

Modified: pypy/dist/pypy/translator/c/database.py
==============================================================================
--- pypy/dist/pypy/translator/c/database.py	(original)
+++ pypy/dist/pypy/translator/c/database.py	Sun May 14 17:37:36 2006
@@ -151,7 +151,7 @@
             nodefactory = ContainerNodeFactory[T.__class__]
             node = nodefactory(self, T, container)
             self.containernodes[container] = node
-            if getattr(container, 'isgchelper', False):
+            if node.is_later_container:
                 self.latercontainerlist.append(node)
             else:
                 self.containerlist.append(node)

Modified: pypy/dist/pypy/translator/c/funcgen.py
==============================================================================
--- pypy/dist/pypy/translator/c/funcgen.py	(original)
+++ pypy/dist/pypy/translator/c/funcgen.py	Sun May 14 17:37:36 2006
@@ -96,18 +96,17 @@
     def name(self, cname):  #virtual
         return cname
 
-    def implementation_begin(self):
+    def patch_graph(self, copy_graph):
+        graph = self.graph
         if self.db.gctransformer.inline:
-            newgraph = copygraph(self.graph, shallow=True)
-            self.oldgraph = self.graph
-            self.graph = newgraph
-            ## protect
-            #for block in self.oldgraph.iterblocks():
-            #    for op in block.operations:
-            #        op.args = tuple(op.args)
-            self.db.gctransformer.inline_helpers(newgraph)
-        else:
-            self.oldgraph = self.graph
+            if copy_graph:
+                graph = copygraph(graph, shallow=True)
+            self.db.gctransformer.inline_helpers(graph)
+        return graph
+
+    def implementation_begin(self):
+        self.oldgraph = self.graph
+        self.graph = self.patch_graph(copy_graph=True)
         SSI_to_SSA(self.graph)
         self.collect_var_and_types()
         self.blocknum = {}

Modified: pypy/dist/pypy/translator/c/genc.py
==============================================================================
--- pypy/dist/pypy/translator/c/genc.py	(original)
+++ pypy/dist/pypy/translator/c/genc.py	Sun May 14 17:37:36 2006
@@ -1,6 +1,6 @@
 import autopath
 import py
-from pypy.translator.c.node import PyObjectNode
+from pypy.translator.c.node import PyObjectNode, FuncNode
 from pypy.translator.c.database import LowLevelDatabase
 from pypy.translator.c.extfunc import pre_include_code_lines
 from pypy.translator.gensupp import uniquemodulename, NameManager
@@ -132,6 +132,16 @@
             self.gen_makefile(targetdir)
         return cfile 
 
+    def generate_graphs_for_llinterp(self, db=None):
+        # prepare the graphs as when the source is generated, but without
+        # actually generating the source.
+        if db is None:
+            db = self.build_database()
+        for node in db.containerlist:
+            if isinstance(node, FuncNode):
+                for funcgen in node.funcgens:
+                    funcgen.patch_graph(copy_graph=False)
+
 
 class CExtModuleBuilder(CBuilder):
     standalone = False

Modified: pypy/dist/pypy/translator/c/node.py
==============================================================================
--- pypy/dist/pypy/translator/c/node.py	(original)
+++ pypy/dist/pypy/translator/c/node.py	Sun May 14 17:37:36 2006
@@ -335,6 +335,7 @@
 
 
 class ContainerNode(object):
+    is_later_container = False
     if USESLOTS:
         __slots__ = """db T obj 
                        typename implementationtypename
@@ -555,6 +556,8 @@
             self.name = db.namespace.uniquename('g_' + self.basename())
         if not getattr(obj, 'isgchelper', False):
             self.make_funcgens()
+        else:
+            self.is_later_container = True
         #self.dependencies = {}
         self.typename = db.gettype(T)  #, who_asks=self)
         self.ptrname = self.name

Modified: pypy/dist/pypy/translator/c/test/test_stackless.py
==============================================================================
--- pypy/dist/pypy/translator/c/test/test_stackless.py	(original)
+++ pypy/dist/pypy/translator/c/test/test_stackless.py	Sun May 14 17:37:36 2006
@@ -2,8 +2,7 @@
 from pypy.translator.backendopt.all import backend_optimizations
 from pypy.translator.c.genc import CStandaloneBuilder
 from pypy.translator.c import gc
-from pypy.annotation.model import SomeList, SomeString
-from pypy.annotation.listdef import ListDef
+from pypy.annotation.listdef import s_list_of_strings
 from pypy.rpython.rstack import stack_unwind, stack_frames_depth, stack_too_big
 from pypy.rpython.rstack import yield_current_frame_to_caller
 import os
@@ -32,8 +31,6 @@
             os.write(1, str(fn())+"\n")
             return 0
 
-        s_list_of_strings = SomeList(ListDef(None, SomeString()))
-        s_list_of_strings.listdef.resize()
         t = TranslationContext()
         self.t = t
         t.buildannotator().build_types(entry_point, [s_list_of_strings])

Modified: pypy/dist/pypy/translator/c/test/test_standalone.py
==============================================================================
--- pypy/dist/pypy/translator/c/test/test_standalone.py	(original)
+++ pypy/dist/pypy/translator/c/test/test_standalone.py	Sun May 14 17:37:36 2006
@@ -1,7 +1,6 @@
 from pypy.translator.translator import TranslationContext
 from pypy.translator.c.genc import CStandaloneBuilder
-from pypy.annotation.model import SomeList, SomeString
-from pypy.annotation.listdef import ListDef
+from pypy.annotation.listdef import s_list_of_strings
 import os
 
 
@@ -14,8 +13,6 @@
             os.write(1, "   '" + str(s) + "'\n")
         return 0
 
-    s_list_of_strings = SomeList(ListDef(None, SomeString()))
-    s_list_of_strings.listdef.resize()
     t = TranslationContext()
     t.buildannotator().build_types(entry_point, [s_list_of_strings])
     t.buildrtyper().specialize()

Modified: pypy/dist/pypy/translator/driver.py
==============================================================================
--- pypy/dist/pypy/translator/driver.py	(original)
+++ pypy/dist/pypy/translator/driver.py	Sun May 14 17:37:36 2006
@@ -4,7 +4,7 @@
 from pypy.translator.tool.taskengine import SimpleTaskEngine
 from pypy.translator.goal import query
 from pypy.annotation import model as annmodel
-from pypy.annotation import listdef
+from pypy.annotation.listdef import s_list_of_strings
 from pypy.annotation import policy as annpolicy
 import optparse
 
@@ -106,9 +106,7 @@
         self.standalone = standalone
 
         if standalone:
-            ldef = listdef.ListDef(None, annmodel.SomeString())
-            ldef.resize()
-            inputtypes = [annmodel.SomeList(ldef)]
+            inputtypes = [s_list_of_strings]
         self.inputtypes = inputtypes
 
         if policy is None:

Modified: pypy/dist/pypy/translator/goal/targetlogic.py
==============================================================================
--- pypy/dist/pypy/translator/goal/targetlogic.py	(original)
+++ pypy/dist/pypy/translator/goal/targetlogic.py	Sun May 14 17:37:36 2006
@@ -3,8 +3,6 @@
 # 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 pypy.interpreter.error import OperationError
 from pypy.translator.goal.ann_override import PyPyAnnotatorPolicy

Modified: pypy/dist/pypy/translator/goal/targetlogicstandalone.py
==============================================================================
--- pypy/dist/pypy/translator/goal/targetlogicstandalone.py	(original)
+++ pypy/dist/pypy/translator/goal/targetlogicstandalone.py	Sun May 14 17:37:36 2006
@@ -3,8 +3,6 @@
 # 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 pypy.interpreter.error import OperationError
 from pypy.translator.goal.ann_override import PyPyAnnotatorPolicy

Modified: pypy/dist/pypy/translator/goal/targetmultiplespaces.py
==============================================================================
--- pypy/dist/pypy/translator/goal/targetmultiplespaces.py	(original)
+++ pypy/dist/pypy/translator/goal/targetmultiplespaces.py	Sun May 14 17:37:36 2006
@@ -3,8 +3,6 @@
 # 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 pypy.interpreter.error import OperationError
 from pypy.translator.goal.ann_override import PyPyAnnotatorPolicy

Modified: pypy/dist/pypy/translator/goal/targetpypy_stacklesstest.py
==============================================================================
--- pypy/dist/pypy/translator/goal/targetpypy_stacklesstest.py	(original)
+++ pypy/dist/pypy/translator/goal/targetpypy_stacklesstest.py	Sun May 14 17:37:36 2006
@@ -11,8 +11,6 @@
 # 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 pypy.interpreter.error import OperationError
 from pypy.translator.goal.ann_override import PyPyAnnotatorPolicy

Modified: pypy/dist/pypy/translator/goal/targetpypymain.py
==============================================================================
--- pypy/dist/pypy/translator/goal/targetpypymain.py	(original)
+++ pypy/dist/pypy/translator/goal/targetpypymain.py	Sun May 14 17:37:36 2006
@@ -3,8 +3,7 @@
 # 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.annotation.model import SomeString
 from pypy.interpreter import gateway
 from pypy.interpreter.error import OperationError
 from pypy.translator.goal.ann_override import PyPyAnnotatorPolicy

Modified: pypy/dist/pypy/translator/goal/targetpypystandalone.py
==============================================================================
--- pypy/dist/pypy/translator/goal/targetpypystandalone.py	(original)
+++ pypy/dist/pypy/translator/goal/targetpypystandalone.py	Sun May 14 17:37:36 2006
@@ -11,8 +11,6 @@
 # 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 pypy.interpreter.error import OperationError
 from pypy.translator.goal.ann_override import PyPyAnnotatorPolicy

Modified: pypy/dist/pypy/translator/goal/targetthunkstandalone.py
==============================================================================
--- pypy/dist/pypy/translator/goal/targetthunkstandalone.py	(original)
+++ pypy/dist/pypy/translator/goal/targetthunkstandalone.py	Sun May 14 17:37:36 2006
@@ -3,8 +3,6 @@
 # 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 pypy.interpreter.error import OperationError
 from pypy.translator.goal.ann_override import PyPyAnnotatorPolicy

Modified: pypy/dist/pypy/translator/llvm/demo/run.py
==============================================================================
--- pypy/dist/pypy/translator/llvm/demo/run.py	(original)
+++ pypy/dist/pypy/translator/llvm/demo/run.py	Sun May 14 17:37:36 2006
@@ -2,8 +2,7 @@
 import os
 import sys
 
-from pypy.annotation.model import SomeList, SomeString
-from pypy.annotation.listdef import ListDef
+from pypy.annotation.listdef import s_list_of_strings
 
 from pypy.translator.translator import TranslationContext
 from pypy.translator.c.genc import CStandaloneBuilder
@@ -16,8 +15,6 @@
     entry_point([])
 
 def c(name):
-    s_list_of_strings = SomeList(ListDef(None, SomeString()))
-    s_list_of_strings.listdef.resize()
     t = TranslationContext()
     t.buildannotator().build_types(entry_point, [s_list_of_strings])
     t.buildrtyper().specialize()
@@ -30,8 +27,6 @@
     os.system(exe_path)
     
 def l(name):
-    s_list_of_strings = SomeList(ListDef(None, SomeString()))
-    s_list_of_strings.listdef.resize()
     exe_path = genllvm_compile(entry_point, [s_list_of_strings],
                                exe_name=name, standalone=True)
     print 'Running standalone (llvm-based) executable:'

Modified: pypy/dist/pypy/translator/stackless/test/test_transform.py
==============================================================================
--- pypy/dist/pypy/translator/stackless/test/test_transform.py	(original)
+++ pypy/dist/pypy/translator/stackless/test/test_transform.py	Sun May 14 17:37:36 2006
@@ -9,7 +9,7 @@
 from pypy.translator.translator import TranslationContext, graphof
 from pypy.objspace.flow.model import checkgraph
 from pypy.annotation import model as annmodel
-from pypy.annotation.listdef import ListDef 
+from pypy.annotation.listdef import s_list_of_strings
 from pypy import conftest
 
 def test_frame_typer():
@@ -227,8 +227,6 @@
                 assert op != block.operations[-1]
 
 def rtype_stackless_function(fn):
-    s_list_of_strings = annmodel.SomeList(ListDef(None, annmodel.SomeString()))
-    s_list_of_strings.listdef.resize()
     t = TranslationContext()
     annotator = t.buildannotator()
     annotator.policy.allow_someobjects = False


From arigo at codespeak.net  Sun May 14 18:57:22 2006
From: arigo at codespeak.net (arigo at codespeak.net)
Date: Sun, 14 May 2006 18:57:22 +0200 (CEST)
Subject: [pypy-svn] r27206 - pypy/dist/pypy/rpython/memory
Message-ID: <20060514165722.47F8A100B6@code0.codespeak.net>

Author: arigo
Date: Sun May 14 18:57:19 2006
New Revision: 27206

Modified:
   pypy/dist/pypy/rpython/memory/convertlltype.py
   pypy/dist/pypy/rpython/memory/gc.py
   pypy/dist/pypy/rpython/memory/lltypelayout.py
Log:
(pedronis, arigo)
Some clean-ups in the memory simulator, needed for the sanity of
what we're working on.


Modified: pypy/dist/pypy/rpython/memory/convertlltype.py
==============================================================================
--- pypy/dist/pypy/rpython/memory/convertlltype.py	(original)
+++ pypy/dist/pypy/rpython/memory/convertlltype.py	Sun May 14 18:57:19 2006
@@ -13,6 +13,16 @@
 FUNCTIONTYPES = (types.FunctionType, types.UnboundMethodType,
                  types.BuiltinFunctionType)
 
+
+def get_real_value(val_or_ptr):
+    if isinstance(val_or_ptr, llmemory.AddressOffset):
+        return lltypelayout.convert_offset_to_int(val_or_ptr)
+    return val_or_ptr
+
+def size_gc_header(gc, typeid):
+    return get_real_value(gc.size_gc_header(typeid))
+
+
 class LLTypeConverter(object):
     def __init__(self, address, gc=None, qt=None):
         self.type_to_typeid = {}
@@ -27,9 +37,7 @@
         TYPE = lltype.typeOf(val_or_ptr)
         if isinstance(TYPE, lltype.Primitive):
             assert inline_to_ptr is None
-            if isinstance(val_or_ptr, llmemory.AddressOffset):
-                return lltypelayout.convert_offset_to_int(val_or_ptr)
-            return val_or_ptr
+            return get_real_value(val_or_ptr)
         elif isinstance(TYPE, lltype.Array):
             return self.convert_array(val_or_ptr, inline_to_ptr)
         elif isinstance(TYPE, lltype.Struct):
@@ -61,8 +69,8 @@
             if self.gc is not None:
                 typeid = self.query_types.get_typeid(TYPE)
                 self.gc.init_gc_object_immortal(startaddr, typeid)
-                startaddr += self.gc.size_gc_header(typeid)
-                self.curraddress += self.gc.size_gc_header(typeid)
+                startaddr += size_gc_header(self.gc, typeid)
+                self.curraddress += size_gc_header(self.gc, typeid)
             ptr = init_object_on_address(startaddr, TYPE, arraylength)
             self.constantroots.append(ptr)
         self.converted[_array] = ptr
@@ -101,8 +109,8 @@
             if self.gc is not None:
                 typeid = self.query_types.get_typeid(TYPE)
                 self.gc.init_gc_object_immortal(startaddr, typeid)
-                startaddr += self.gc.size_gc_header(typeid)
-                self.curraddress += self.gc.size_gc_header(typeid)
+                startaddr += size_gc_header(self.gc, typeid)
+                self.curraddress += size_gc_header(self.gc, typeid)
             ptr = init_object_on_address(startaddr, TYPE, inlinedarraylength)
             self.constantroots.append(ptr)
         self.converted[_struct] = ptr
@@ -189,7 +197,7 @@
                 total_size += sizeof(cand._TYPE, length)
                 if self.gc is not None:
                     typeid = self.query_types.get_typeid(cand._TYPE)
-                    total_size += self.gc.size_gc_header(typeid)
+                    total_size += size_gc_header(self.gc, typeid)
                 for item in cand.items:
                     candidates.append(item)
             elif isinstance(cand, lltype._struct):
@@ -209,7 +217,7 @@
                         total_size += sizeof(TYPE)
                     if self.gc is not None:
                         typeid = self.query_types.get_typeid(TYPE)
-                        total_size += self.gc.size_gc_header(typeid)
+                        total_size += size_gc_header(self.gc, typeid)
                 for name in TYPE._flds:
                     candidates.append(getattr(cand, name))
             elif isinstance(cand, lltype._opaque):

Modified: pypy/dist/pypy/rpython/memory/gc.py
==============================================================================
--- pypy/dist/pypy/rpython/memory/gc.py	(original)
+++ pypy/dist/pypy/rpython/memory/gc.py	Sun May 14 18:57:19 2006
@@ -11,14 +11,8 @@
 int_size = lltypesimulation.sizeof(lltype.Signed)
 
 class GCHeaderOffset(llmemory.AddressOffset):
-    def __init__(self, minimal_size):
-        self.minimal_size = minimal_size
-    def __int__(self):
-        from pypy.rpython.memory.lltypelayout import sizeof
-        return sizeof(self.minimal_size)
-    # XXX blech
-    def __radd__(self, other):
-        return int(self) + other
+    def __init__(self, minimal_layout):
+        self.minimal_layout = minimal_layout
 
 gc_header_two_ints = GCHeaderOffset(
     lltype.Struct("header", ("a", lltype.Signed), ("b", lltype.Signed)))

Modified: pypy/dist/pypy/rpython/memory/lltypelayout.py
==============================================================================
--- pypy/dist/pypy/rpython/memory/lltypelayout.py	(original)
+++ pypy/dist/pypy/rpython/memory/lltypelayout.py	Sun May 14 18:57:19 2006
@@ -102,7 +102,7 @@
     elif isinstance(offset, llmemory.ArrayItemsOffset):
         return get_fixed_size(lltype.Signed)
     elif isinstance(offset, GCHeaderOffset):
-        return sizeof(offset.minimal_size)
+        return sizeof(offset.minimal_layout)
     else:
         raise Exception("unknown offset type %r"%offset)
         


From arigo at codespeak.net  Sun May 14 18:59:21 2006
From: arigo at codespeak.net (arigo at codespeak.net)
Date: Sun, 14 May 2006 18:59:21 +0200 (CEST)
Subject: [pypy-svn] r27207 - in pypy/dist/pypy/rpython: . lltypesystem
	lltypesystem/test
Message-ID: <20060514165921.11985100B6@code0.codespeak.net>

Author: arigo
Date: Sun May 14 18:59:19 2006
New Revision: 27207

Added:
   pypy/dist/pypy/rpython/lltypesystem/llheap.py   (contents, props changed)
Modified:
   pypy/dist/pypy/rpython/llinterp.py
   pypy/dist/pypy/rpython/lltypesystem/llmemory.py
   pypy/dist/pypy/rpython/lltypesystem/test/test_llmemory.py
Log:
(pedronis, arigo)
Started work on llmemory.raw_malloc(), which returns
a fakeaddress instead of using the memory simulator.
The ultimate goal is to get rid of the latter.  Ah ah!


Modified: pypy/dist/pypy/rpython/llinterp.py
==============================================================================
--- pypy/dist/pypy/rpython/llinterp.py	(original)
+++ pypy/dist/pypy/rpython/llinterp.py	Sun May 14 18:59:19 2006
@@ -1,6 +1,6 @@
 from pypy.objspace.flow.model import FunctionGraph, Constant, Variable, c_last_exception
 from pypy.rpython.rarithmetic import intmask, r_uint, ovfcheck, r_longlong, r_ulonglong
-from pypy.rpython.lltypesystem import lltype, llmemory, lloperation
+from pypy.rpython.lltypesystem import lltype, llmemory, lloperation, llheap
 from pypy.rpython.ootypesystem import ootype
 from pypy.rpython.objectmodel import ComputedIntSymbolic
 
@@ -36,7 +36,7 @@
 class LLInterpreter(object):
     """ low level interpreter working with concrete values. """
 
-    def __init__(self, typer, heap=lltype, tracing=True):
+    def __init__(self, typer, heap=llheap, tracing=True):
         self.bindings = {}
         self.typer = typer
         self.heap = heap  #module that provides malloc, etc for lltypes
@@ -480,7 +480,7 @@
         return self.op_direct_call(f, *args)
 
     def op_unsafe_call(self, TGT, f):
-        assert isinstance(f, llmemory.fakeaddress)
+        checkadr(f)
         assert f.offset is None
         obj = self.llinterpreter.typer.type_system.deref(f.ob)
         assert hasattr(obj, 'graph') # don't want to think about that

Added: pypy/dist/pypy/rpython/lltypesystem/llheap.py
==============================================================================
--- (empty file)
+++ pypy/dist/pypy/rpython/lltypesystem/llheap.py	Sun May 14 18:59:19 2006
@@ -0,0 +1,4 @@
+# only for the LLInterpreter.  Don't use directly.
+
+from pypy.rpython.lltypesystem.lltype import pyobjectptr, malloc, free
+from pypy.rpython.lltypesystem.llmemory import raw_malloc, raw_free

Modified: pypy/dist/pypy/rpython/lltypesystem/llmemory.py
==============================================================================
--- pypy/dist/pypy/rpython/lltypesystem/llmemory.py	(original)
+++ pypy/dist/pypy/rpython/lltypesystem/llmemory.py	Sun May 14 18:59:19 2006
@@ -78,7 +78,7 @@
         self.TYPE = TYPE
 
     def __repr__(self):
-        return '< ArrayItemsOffset >'
+        return '< ArrayItemsOffset %r >' % (self.TYPE,)
 
     def ref(self, arrayref):
         array = arrayref.get()
@@ -91,7 +91,7 @@
         self.TYPE = TYPE
 
     def __repr__(self):
-        return '< ArrayLengthOffset >'
+        return '< ArrayLengthOffset %r >' % (self.TYPE,)
 
     def ref(self, arrayref):
         array = arrayref.get()
@@ -116,7 +116,8 @@
     def get(self):
         return len(self.array)
     def set(self, value):
-        raise Exception("can't assign to an array's length")
+        if value != len(self.array):
+            raise Exception("can't change the length of an array")
     def type(self):
         return lltype.Signed
 
@@ -235,12 +236,14 @@
             # special case that requires direct_fieldptr
             return lltype.direct_fieldptr(ref.struct,
                                           ref.fieldname)
-        elif (isinstance(EXPECTED_TYPE.TO, lltype.OpaqueType) or
-              isinstance(ref.type().TO, lltype.OpaqueType)):
-            return lltype.cast_opaque_ptr(EXPECTED_TYPE, ref.get())
         else:
-            # regular case
-            return lltype.cast_pointer(EXPECTED_TYPE, ref.get())
+            result = ref.get()
+            if (isinstance(EXPECTED_TYPE.TO, lltype.OpaqueType) or
+                isinstance(lltype.typeOf(result).TO, lltype.OpaqueType)):
+                return lltype.cast_opaque_ptr(EXPECTED_TYPE, result)
+            else:
+                # regular case
+                return lltype.cast_pointer(EXPECTED_TYPE, result)
 
     def _cast_to_int(self):
         if self:
@@ -320,3 +323,22 @@
 def cast_adr_to_int(adr):
     return adr._cast_to_int()
 
+# ____________________________________________________________
+
+def raw_malloc(size):
+    if isinstance(size, ItemOffset):
+        T = lltype.FixedSizeArray(size.TYPE, size.repeat)
+        p = lltype.malloc(T, immortal=True)
+        array_adr = cast_ptr_to_adr(p)
+        return array_adr + ArrayItemsOffset(T)
+    elif isinstance(size, CompositeOffset):
+        if (isinstance(size.first, ArrayItemsOffset) and
+            isinstance(size.second, ItemOffset)):
+            assert size.first.TYPE.OF == size.second.TYPE
+            T = size.first.TYPE
+            p = lltype.malloc(T, size.second.repeat, immortal=True)
+            return cast_ptr_to_adr(p)
+    raise NotImplementedError(size)
+
+def raw_free(adr):
+    pass   # for now

Modified: pypy/dist/pypy/rpython/lltypesystem/test/test_llmemory.py
==============================================================================
--- pypy/dist/pypy/rpython/lltypesystem/test/test_llmemory.py	(original)
+++ pypy/dist/pypy/rpython/lltypesystem/test/test_llmemory.py	Sun May 14 18:59:19 2006
@@ -193,3 +193,53 @@
     adr2 = cast_ptr_to_adr(o)
     s2 = cast_adr_to_ptr(adr2, lltype.Ptr(S))
     assert s2 == s
+
+def test_raw_malloc_struct():
+    T = lltype.GcStruct('T', ('z', lltype.Signed))
+    S = lltype.Struct('S', ('x', lltype.Signed), ('y', lltype.Ptr(T)))
+    adr = raw_malloc(sizeof(S))
+    s = cast_adr_to_ptr(adr, lltype.Ptr(S))
+    assert lltype.typeOf(s) == lltype.Ptr(S)
+    s.x = 123
+    x_adr = adr + offsetof(S, 'x')
+    assert x_adr.signed[0] == 123
+    x_adr.signed[0] = 124
+    assert s.x == 124
+
+def test_raw_malloc_signed():
+    adr = raw_malloc(sizeof(lltype.Signed))
+    p = cast_adr_to_ptr(adr,
+                        lltype.Ptr(lltype.FixedSizeArray(lltype.Signed, 1)))
+    p[0] = 123
+    assert adr.signed[0] == 123
+    adr.signed[0] = 124
+    assert p[0] == 124
+    py.test.raises(IndexError, "adr.signed[-1]")
+    py.test.raises(IndexError, "adr.signed[1]")
+
+def test_raw_malloc_signed_bunch():
+    adr = raw_malloc(sizeof(lltype.Signed) * 50)
+    p = cast_adr_to_ptr(adr,
+                        lltype.Ptr(lltype.FixedSizeArray(lltype.Signed, 1)))
+    for i in range(50):
+        p[i] = 123 + i
+        assert adr.signed[i] == 123 + i
+        adr.signed[i] = 124 - i
+        assert p[i] == 124 - i
+    py.test.raises(IndexError, "adr.signed[50]")
+
+def test_raw_malloc_array():
+    A = lltype.Array(lltype.Signed)
+    adr = raw_malloc(sizeof(A, 50))
+    length_adr = adr + ArrayLengthOffset(A)
+    length_adr.signed[0] = 50
+    p = cast_adr_to_ptr(adr, lltype.Ptr(A))
+    assert len(p) == 50
+    for i in range(50):
+        item_adr = adr + itemoffsetof(A, i)
+        p[i] = 123 + i
+        assert item_adr.signed[0] == 123 + i
+        item_adr.signed[0] = 124 - i
+        assert p[i] == 124 - i
+    item_adr = adr + itemoffsetof(A, 50)
+    py.test.raises(IndexError, "item_adr.signed[0]")


From arigo at codespeak.net  Sun May 14 19:40:15 2006
From: arigo at codespeak.net (arigo at codespeak.net)
Date: Sun, 14 May 2006 19:40:15 +0200 (CEST)
Subject: [pypy-svn] r27208 - pypy/dist/pypy/rpython/memory
Message-ID: <20060514174015.13C9610092@code0.codespeak.net>

Author: arigo
Date: Sun May 14 19:40:11 2006
New Revision: 27208

Modified:
   pypy/dist/pypy/rpython/memory/gc.py
   pypy/dist/pypy/rpython/memory/gclltype.py
Log:
(pedronis, arigo standing by impressed)

Skip in just the one place responsible for half of the tests failing.
The other half of the tests are fine.


Modified: pypy/dist/pypy/rpython/memory/gc.py
==============================================================================
--- pypy/dist/pypy/rpython/memory/gc.py	(original)
+++ pypy/dist/pypy/rpython/memory/gc.py	Sun May 14 19:40:11 2006
@@ -142,7 +142,7 @@
         if can_collect and self.bytes_malloced > self.heap_size:
             self.collect()
         size_gc_header = MarkSweepGC._size_gc_header
-        result = raw_malloc(size + size_gc_header)
+        result = raw_malloc(size_gc_header + size)
         result.signed[0] = typeid << 1
         self.malloced_objects.append(result)
         self.bytes_malloced += size + size_gc_header
@@ -158,8 +158,8 @@
             raise MemoryError
         size += varsize
         size_gc_header = MarkSweepGC._size_gc_header
-        result = raw_malloc(size + size_gc_header)
-        (result + offset_to_length + size_gc_header).signed[0] = length
+        result = raw_malloc(size_gc_header + size)
+        (result + size_gc_header + offset_to_length).signed[0] = length
         result.signed[0] = typeid << 1
         self.malloced_objects.append(result)
         self.bytes_malloced += size + size_gc_header

Modified: pypy/dist/pypy/rpython/memory/gclltype.py
==============================================================================
--- pypy/dist/pypy/rpython/memory/gclltype.py	(original)
+++ pypy/dist/pypy/rpython/memory/gclltype.py	Sun May 14 19:40:11 2006
@@ -25,6 +25,7 @@
 from pypy.rpython.memory.gc import MarkSweepGC, SemiSpaceGC
 use_gc = MarkSweepGC
 def create_gc(llinterp, flowgraphs):
+    import py; py.test.skip("out-of-progress")
     from pypy.rpython.memory.gcwrapper import GcWrapper, AnnotatingGcWrapper
     wrapper = GcWrapper(llinterp, flowgraphs, use_gc)
     return wrapper


From arigo at codespeak.net  Mon May 15 00:47:02 2006
From: arigo at codespeak.net (arigo at codespeak.net)
Date: Mon, 15 May 2006 00:47:02 +0200 (CEST)
Subject: [pypy-svn] r27210 - in pypy/dist/pypy: annotation rpython
	rpython/lltypesystem rpython/lltypesystem/test rpython/memory
	rpython/memory/test translator/c translator/c/src
Message-ID: <20060514224702.A4385100B6@code0.codespeak.net>

Author: arigo
Date: Mon May 15 00:46:57 2006
New Revision: 27210

Modified:
   pypy/dist/pypy/annotation/builtin.py
   pypy/dist/pypy/rpython/llinterp.py
   pypy/dist/pypy/rpython/lltypesystem/llheap.py
   pypy/dist/pypy/rpython/lltypesystem/llmemory.py
   pypy/dist/pypy/rpython/lltypesystem/lloperation.py
   pypy/dist/pypy/rpython/lltypesystem/lltype.py
   pypy/dist/pypy/rpython/lltypesystem/test/test_llmemory.py
   pypy/dist/pypy/rpython/memory/gc.py
   pypy/dist/pypy/rpython/memory/gctransform.py
   pypy/dist/pypy/rpython/memory/lladdress.py
   pypy/dist/pypy/rpython/memory/lltypelayout.py
   pypy/dist/pypy/rpython/memory/lltypesimulation.py
   pypy/dist/pypy/rpython/memory/support.py
   pypy/dist/pypy/rpython/memory/test/test_gc.py
   pypy/dist/pypy/rpython/memory/test/test_gctransform.py
   pypy/dist/pypy/rpython/memory/test/test_support.py
   pypy/dist/pypy/rpython/rbuiltin.py
   pypy/dist/pypy/translator/c/genc.py
   pypy/dist/pypy/translator/c/node.py
   pypy/dist/pypy/translator/c/primitive.py
   pypy/dist/pypy/translator/c/src/address.h
Log:
(pedronis, arigo)

after quite a bit of refactoring here and there, the first test with
the framework gc running on top of the llinterp passes.



Modified: pypy/dist/pypy/annotation/builtin.py
==============================================================================
--- pypy/dist/pypy/annotation/builtin.py	(original)
+++ pypy/dist/pypy/annotation/builtin.py	Mon May 15 00:46:57 2006
@@ -544,6 +544,10 @@
     assert isinstance(s_size, SomeInteger) #XXX add noneg...?
     return SomeAddress()
 
+def raw_malloc_usage(s_size):
+    assert isinstance(s_size, SomeInteger) #XXX add noneg...?
+    return SomeInteger(nonneg=True)
+
 def raw_free(s_addr):
     assert isinstance(s_addr, SomeAddress)
     assert not s_addr.is_null
@@ -556,6 +560,7 @@
     assert isinstance(s_int, SomeInteger) #XXX add noneg...?
 
 BUILTIN_ANALYZERS[lladdress.raw_malloc] = raw_malloc
+BUILTIN_ANALYZERS[lladdress.raw_malloc_usage] = raw_malloc_usage
 BUILTIN_ANALYZERS[lladdress.raw_free] = raw_free
 BUILTIN_ANALYZERS[lladdress.raw_memcopy] = raw_memcopy
 

Modified: pypy/dist/pypy/rpython/llinterp.py
==============================================================================
--- pypy/dist/pypy/rpython/llinterp.py	(original)
+++ pypy/dist/pypy/rpython/llinterp.py	Mon May 15 00:46:57 2006
@@ -757,6 +757,10 @@
         assert lltype.typeOf(size) == lltype.Signed
         return self.heap.raw_malloc(size)
 
+    def op_raw_malloc_usage(self, size):
+        assert lltype.typeOf(size) == lltype.Signed
+        return self.heap.raw_malloc_usage(size)
+
     def op_raw_free(self, addr):
         assert checkadr(addr) 
         self.heap.raw_free(addr)
@@ -925,6 +929,14 @@
         else:
             return self.original_int_mul(x, y)
 
+    original_int_mul_ovf = op_int_mul_ovf
+
+    def op_int_mul_ovf(self, x, y):
+        if isinstance(x, llmemory.AddressOffset):
+            return x * y
+        else:
+            return self.original_int_mul_ovf(x, y)
+
     def op_unichar_eq(self, x, y):
         assert isinstance(x, unicode) and len(x) == 1
         assert isinstance(y, unicode) and len(y) == 1

Modified: pypy/dist/pypy/rpython/lltypesystem/llheap.py
==============================================================================
--- pypy/dist/pypy/rpython/lltypesystem/llheap.py	(original)
+++ pypy/dist/pypy/rpython/lltypesystem/llheap.py	Mon May 15 00:46:57 2006
@@ -2,3 +2,4 @@
 
 from pypy.rpython.lltypesystem.lltype import pyobjectptr, malloc, free
 from pypy.rpython.lltypesystem.llmemory import raw_malloc, raw_free
+from pypy.rpython.lltypesystem.llmemory import raw_malloc_usage

Modified: pypy/dist/pypy/rpython/lltypesystem/llmemory.py
==============================================================================
--- pypy/dist/pypy/rpython/lltypesystem/llmemory.py	(original)
+++ pypy/dist/pypy/rpython/lltypesystem/llmemory.py	Mon May 15 00:46:57 2006
@@ -21,6 +21,9 @@
             return NotImplemented
         return CompositeOffset(self, other)
 
+    def raw_malloc(self, rest):
+        raise NotImplementedError("raw_malloc(%r, %r)" % (self, rest))
+
 
 class ItemOffset(AddressOffset):
 
@@ -36,6 +39,9 @@
             return NotImplemented
         return ItemOffset(self.TYPE, self.repeat * other)
 
+    def __neg__(self):
+        return ItemOffset(self.TYPE, -self.repeat)
+
     def ref(self, firstitemref):
         assert isinstance(firstitemref, _arrayitemref)
         array = firstitemref.array
@@ -43,6 +49,19 @@
         index = firstitemref.index + self.repeat
         return _arrayitemref(array, index)
 
+    def raw_malloc(self, rest):
+        assert not rest
+        if (isinstance(self.TYPE, lltype.ContainerType)
+            and self.TYPE._gcstatus()):
+            assert self.repeat == 1
+            p = lltype.malloc(self.TYPE)
+            return cast_ptr_to_adr(p)
+        else:
+            T = lltype.FixedSizeArray(self.TYPE, self.repeat)
+            p = lltype.malloc(T, immortal=True)
+            array_adr = cast_ptr_to_adr(p)
+            return array_adr + ArrayItemsOffset(T)
+
 
 class FieldOffset(AddressOffset):
 
@@ -58,18 +77,50 @@
         assert lltype.typeOf(struct).TO == self.TYPE
         return _structfieldref(struct, self.fldname)
 
+    def raw_malloc(self, rest, parenttype=None):
+        if self.fldname != self.TYPE._arrayfld:
+            return AddressOffset.raw_malloc(self, rest)   # for the error msg
+        assert rest
+        return rest[0].raw_malloc(rest[1:], parenttype=parenttype or self.TYPE)
+
 
 class CompositeOffset(AddressOffset):
 
-    def __init__(self, first, second):
-        self.first = first
-        self.second = second
+    def __new__(cls, *offsets):
+        lst = []
+        for item in offsets:
+            if isinstance(item, CompositeOffset):
+                lst.extend(item.offsets)
+            else:
+                lst.append(item)
+        for i in range(len(lst)-2, -1, -1):
+            if (isinstance(lst[i], ItemOffset) and
+                isinstance(lst[i+1], ItemOffset) and
+                lst[i].TYPE == lst[i+1].TYPE):
+                lst[i:i+2] = [ItemOffset(lst[i].TYPE,
+                                         lst[i].repeat + lst[i+1].repeat)]
+        if len(lst) == 1:
+            return lst[0]
+        else:
+            self = object.__new__(cls)
+            self.offsets = lst
+            return self
 
     def __repr__(self):
-        return '< %r + %r >'%(self.first, self.second)
+        return '< %s >' % (' + '.join([repr(item) for item in self.offsets]),)
 
-    def ref(self, containerref):
-        return self.second.ref(self.first.ref(containerref))
+    def __neg__(self):
+        ofs = [-item for item in self.offsets]
+        ofs.reverse()
+        return CompositeOffset(*ofs)
+
+    def ref(self, ref):
+        for item in self.offsets:
+            ref = item.ref(ref)
+        return ref
+
+    def raw_malloc(self, rest):
+        return self.offsets[0].raw_malloc(self.offsets[1:] + rest)
 
 
 class ArrayItemsOffset(AddressOffset):
@@ -85,6 +136,21 @@
         assert lltype.typeOf(array).TO == self.TYPE
         return _arrayitemref(array, index=0)
 
+    def raw_malloc(self, rest, parenttype=None):
+        if rest:
+            assert len(rest) == 1
+            assert isinstance(rest[0], ItemOffset)
+            assert self.TYPE.OF == rest[0].TYPE
+            count = rest[0].repeat
+        else:
+            count = 0
+        if self.TYPE._hints.get('isrpystring'):
+            count -= 1  # because malloc() will give us the extra char for free
+        p = lltype.malloc(parenttype or self.TYPE, count,
+                          immortal = not self.TYPE._gcstatus())
+        return cast_ptr_to_adr(p)
+
+
 class ArrayLengthOffset(AddressOffset):
 
     def __init__(self, TYPE):
@@ -99,6 +165,57 @@
         return _arraylenref(array)
 
 
+class GCHeaderOffset(AddressOffset):
+    def __init__(self, minimal_layout):
+        self.minimal_layout = minimal_layout
+
+    def __repr__(self):
+        return '< GCHeaderOffset >'
+
+    def __neg__(self):
+        return GCHeaderAntiOffset(self.minimal_layout)
+
+    def ref(self, headerref):
+        header = headerref.get()
+        gcobj = _gc_header2struct[header._obj]
+        return _obref(lltype._ptr(lltype.Ptr(gcobj._TYPE), gcobj))
+
+    def raw_malloc(self, rest):
+        assert rest
+        if isinstance(rest[0], GCHeaderAntiOffset):
+            return rest[1].raw_malloc(rest[2:])    # just for fun
+        gcobjadr = rest[0].raw_malloc(rest[1:])
+        return gcobjadr - self
+
+
+class GCHeaderAntiOffset(AddressOffset):
+    def __init__(self, minimal_layout):
+        self.minimal_layout = minimal_layout
+
+    def __repr__(self):
+        return '< GCHeaderAntiOffset >'
+
+    def __neg__(self):
+        return GCHeaderOffset(self.minimal_layout)
+
+    def ref(self, gcptrref):
+        gcptr = gcptrref.get()
+        try:
+            headerobj = _gc_struct2header[gcptr._obj]
+        except KeyError:
+            headerobj = lltype.malloc(self.minimal_layout,
+                                      immortal=True)._obj
+            _gc_struct2header[gcptr._obj] = headerobj
+            _gc_header2struct[headerobj] = gcptr._obj
+        p = lltype._ptr(lltype.Ptr(headerobj._TYPE), headerobj, True)
+        return _obref(p)
+
+    def raw_malloc(self, rest):
+        assert rest
+        assert isinstance(rest[0], GCHeaderOffset)
+        return rest[1].raw_malloc(rest[2:])
+
+
 class _arrayitemref(object):
     def __init__(self, array, index):
         self.array = array
@@ -188,6 +305,11 @@
             return fakeaddress(self.ob, offset)
         return NotImplemented
 
+    def __sub__(self, other):
+        if isinstance(other, AddressOffset):
+            return self + (-other)
+        return NotImplemented
+
     def __nonzero__(self):
         return self.ob is not None
 
@@ -325,20 +447,21 @@
 
 # ____________________________________________________________
 
+import weakref
+_gc_struct2header = weakref.WeakKeyDictionary()
+_gc_header2struct = weakref.WeakKeyDictionary()
+
 def raw_malloc(size):
-    if isinstance(size, ItemOffset):
-        T = lltype.FixedSizeArray(size.TYPE, size.repeat)
-        p = lltype.malloc(T, immortal=True)
-        array_adr = cast_ptr_to_adr(p)
-        return array_adr + ArrayItemsOffset(T)
-    elif isinstance(size, CompositeOffset):
-        if (isinstance(size.first, ArrayItemsOffset) and
-            isinstance(size.second, ItemOffset)):
-            assert size.first.TYPE.OF == size.second.TYPE
-            T = size.first.TYPE
-            p = lltype.malloc(T, size.second.repeat, immortal=True)
-            return cast_ptr_to_adr(p)
-    raise NotImplementedError(size)
+    if not isinstance(size, AddressOffset):
+        raise NotImplementedError(size)
+    return size.raw_malloc([])
 
 def raw_free(adr):
     pass   # for now
+
+def raw_malloc_usage(size):
+    if isinstance(size, AddressOffset):
+        # ouah
+        from pypy.rpython.memory.lltypelayout import convert_offset_to_int
+        size = convert_offset_to_int(size)
+    return size

Modified: pypy/dist/pypy/rpython/lltypesystem/lloperation.py
==============================================================================
--- pypy/dist/pypy/rpython/lltypesystem/lloperation.py	(original)
+++ pypy/dist/pypy/rpython/lltypesystem/lloperation.py	Mon May 15 00:46:57 2006
@@ -285,6 +285,7 @@
     # __________ address operations __________
 
     'raw_malloc':           LLOp(canraise=(MemoryError,)),
+    'raw_malloc_usage':     LLOp(sideeffects=False),
     'raw_free':             LLOp(),
     'raw_memcopy':          LLOp(),
     'raw_load':             LLOp(sideeffects=False),

Modified: pypy/dist/pypy/rpython/lltypesystem/lltype.py
==============================================================================
--- pypy/dist/pypy/rpython/lltypesystem/lltype.py	(original)
+++ pypy/dist/pypy/rpython/lltypesystem/lltype.py	Mon May 15 00:46:57 2006
@@ -1098,13 +1098,21 @@
 
     def _str_fields(self):
         fields = []
-        for name in self._TYPE._names:
+        names = self._TYPE._names
+        if len(names) > 10:
+            names = names[:5] + names[-1:]
+            skipped_after = 5
+        else:
+            skipped_after = None
+        for name in names:
             T = self._TYPE._flds[name]
             if isinstance(T, Primitive):
                 reprvalue = repr(getattr(self, name))
             else:
                 reprvalue = '...'
             fields.append('%s=%s' % (name, reprvalue))
+        if skipped_after:
+            fields.insert(skipped_after, '(...)')
         return ', '.join(fields)
 
     def __str__(self):
@@ -1160,8 +1168,16 @@
             return repr(item)
 
     def __str__(self):
-        return 'array [ %s ]' % (', '.join([self._str_item(item)
-                                            for item in self.items]),)
+        items = self.items
+        if len(items) > 20:
+            items = items[:12] + items[-5:]
+            skipped_at = 12
+        else:
+            skipped_at = None
+        items = [self._str_item(item) for item in self.items]
+        if skipped_at:
+            items.insert(skipped_at, '(...)')
+        return 'array [ %s ]' % (', '.join(items),)
 
     def getlength(self):
         return len(self.items)

Modified: pypy/dist/pypy/rpython/lltypesystem/test/test_llmemory.py
==============================================================================
--- pypy/dist/pypy/rpython/lltypesystem/test/test_llmemory.py	(original)
+++ pypy/dist/pypy/rpython/lltypesystem/test/test_llmemory.py	Mon May 15 00:46:57 2006
@@ -243,3 +243,42 @@
         assert p[i] == 124 - i
     item_adr = adr + itemoffsetof(A, 50)
     py.test.raises(IndexError, "item_adr.signed[0]")
+
+def test_raw_malloc_gcstruct():
+    from pypy.rpython.memory import gc
+    HDR = lltype.Struct('header', ('a', lltype.Signed))
+    gchdr = gc.GCHeaderOffset(HDR)
+    S = lltype.GcStruct('S', ('x', lltype.Signed))
+
+    def allocate():
+        adr = raw_malloc(gchdr + sizeof(S))
+        p = cast_adr_to_ptr(adr, lltype.Ptr(HDR))
+        p.a = -21
+        adr = cast_ptr_to_adr(p)
+        sadr = adr + gchdr
+        s = cast_adr_to_ptr(sadr, lltype.Ptr(S))
+        s.x = 123
+        assert (sadr+offsetof(S, 'x')).signed[0] == 123
+        (sadr+offsetof(S, 'x')).signed[0] = 125
+        assert s.x == 125
+        return s
+
+    s = allocate()
+    adr = cast_ptr_to_adr(s) - gchdr
+    p = cast_adr_to_ptr(adr, lltype.Ptr(HDR))
+    assert p.a == -21
+
+def test_raw_malloc_varsize():
+    A = lltype.Array(lltype.Signed)
+    S = lltype.Struct('S', ('x', lltype.Signed), ('y', A))
+    adr = raw_malloc(offsetof(S, 'y') + itemoffsetof(A, 10))
+    length_adr = adr + offsetof(S, 'y') + ArrayLengthOffset(A)
+    length_adr.signed[0] = 10
+
+    p = cast_adr_to_ptr(adr, lltype.Ptr(S))
+    p.y[7] = 5
+    assert (adr + offsetof(S, 'y') + itemoffsetof(A, 7)).signed[0] == 5
+    (adr + offsetof(S, 'y') + itemoffsetof(A, 7)).signed[0] = 18187
+    assert p.y[7] == 18187
+    py.test.raises(IndexError,
+                   "(adr + offsetof(S, 'y') + itemoffsetof(A, 10)).signed[0]")

Modified: pypy/dist/pypy/rpython/memory/gc.py
==============================================================================
--- pypy/dist/pypy/rpython/memory/gc.py	(original)
+++ pypy/dist/pypy/rpython/memory/gc.py	Mon May 15 00:46:57 2006
@@ -1,5 +1,5 @@
 from pypy.rpython.memory.lladdress import raw_malloc, raw_free, raw_memcopy
-from pypy.rpython.memory.lladdress import NULL, _address
+from pypy.rpython.memory.lladdress import NULL, _address, raw_malloc_usage
 from pypy.rpython.memory.support import get_address_linked_list
 from pypy.rpython.memory import lltypesimulation
 from pypy.rpython.lltypesystem import lltype, llmemory
@@ -10,16 +10,11 @@
 
 int_size = lltypesimulation.sizeof(lltype.Signed)
 
-class GCHeaderOffset(llmemory.AddressOffset):
-    def __init__(self, minimal_layout):
-        self.minimal_layout = minimal_layout
+GCHeaderOffset = llmemory.GCHeaderOffset
 
 gc_header_two_ints = GCHeaderOffset(
     lltype.Struct("header", ("a", lltype.Signed), ("b", lltype.Signed)))
 
-gc_header_one_int = GCHeaderOffset(
-    lltype.Struct("header", ("a", lltype.Signed)))
-
 class GCError(Exception):
     pass
 
@@ -111,8 +106,10 @@
 
 class MarkSweepGC(GCBase):
     _alloc_flavor_ = "raw"
-    
-    _size_gc_header = gc_header_one_int
+
+    HDR = lltype.Struct('header', ('typeid', lltype.Signed))
+    HDRPTR = lltype.Ptr(HDR)
+    _size_gc_header = GCHeaderOffset(HDR)
 
     def __init__(self, AddressLinkedList, start_heap_size=4096, get_roots=None):
         self.bytes_malloced = 0
@@ -143,9 +140,10 @@
             self.collect()
         size_gc_header = MarkSweepGC._size_gc_header
         result = raw_malloc(size_gc_header + size)
-        result.signed[0] = typeid << 1
+        hdr = llmemory.cast_adr_to_ptr(result, self.HDRPTR)
+        hdr.typeid = typeid << 1
         self.malloced_objects.append(result)
-        self.bytes_malloced += size + size_gc_header
+        self.bytes_malloced += raw_malloc_usage(size + size_gc_header)
         return result + size_gc_header
 
     def malloc_varsize(self, typeid, length, size, itemsize, offset_to_length,
@@ -153,16 +151,18 @@
         if can_collect and self.bytes_malloced > self.heap_size:
             self.collect()
         try:
-            varsize = rarithmetic.ovfcheck(length * itemsize)
+            varsize = rarithmetic.ovfcheck(itemsize * length)
         except OverflowError:
             raise MemoryError
+        # XXX also check for overflow on the various '+' below!
         size += varsize
         size_gc_header = MarkSweepGC._size_gc_header
         result = raw_malloc(size_gc_header + size)
         (result + size_gc_header + offset_to_length).signed[0] = length
-        result.signed[0] = typeid << 1
+        hdr = llmemory.cast_adr_to_ptr(result, self.HDRPTR)
+        hdr.typeid = typeid << 1
         self.malloced_objects.append(result)
-        self.bytes_malloced += size + size_gc_header
+        self.bytes_malloced += raw_malloc_usage(size + size_gc_header)
         return result + size_gc_header
 
     def collect(self):
@@ -178,10 +178,10 @@
                 break
             # roots is a list of addresses to addresses:
             objects.append(curr.address[0])
-            gc_info = curr.address[0] - MarkSweepGC._size_gc_header
-            # constants roots are not malloced and thus don't have their mark
-            # bit reset
-            gc_info.signed[0] = gc_info.signed[0] & (~1)
+##            # constants roots are not malloced and thus don't have their mark
+##            # bit reset
+##            gc_info = curr.address[0] - MarkSweepGC._size_gc_header
+##            gc_info.signed[0] = gc_info.signed[0] & (~1)
         free_non_gc_object(roots)
         while 1:  #mark
             curr = objects.pop()
@@ -189,9 +189,10 @@
             if curr == NULL:
                 break
             gc_info = curr - MarkSweepGC._size_gc_header
-            if gc_info.signed[0] & 1:
+            hdr = llmemory.cast_adr_to_ptr(gc_info, self.HDRPTR)
+            if hdr.typeid & 1:
                 continue
-            typeid = gc_info.signed[0] >> 1
+            typeid = hdr.typeid >> 1
             offsets = self.offsets_to_gc_pointers(typeid)
             i = 0
             while i < len(offsets):
@@ -213,7 +214,7 @@
                         objects.append((item + offsets[j]).address[0])
                         j += 1
                     i += 1
-            gc_info.signed[0] = gc_info.signed[0] | 1
+            hdr.typeid = hdr.typeid | 1
         free_non_gc_object(objects)
         newmo = self.AddressLinkedList()
         curr_heap_size = 0
@@ -222,17 +223,19 @@
             curr = self.malloced_objects.pop()
             if curr == NULL:
                 break
-            typeid = curr.signed[0] >> 1
+            hdr = llmemory.cast_adr_to_ptr(curr, self.HDRPTR)
+            typeid = hdr.typeid >> 1
             size = self.fixed_size(typeid)
             if self.is_varsize(typeid):
                 length = (curr + MarkSweepGC._size_gc_header + self.varsize_offset_to_length(typeid)).signed[0]
                 size += length * self.varsize_item_sizes(typeid)
-            if curr.signed[0] & 1:
-                curr.signed[0] = curr.signed[0] & (~1)
+            estimate = raw_malloc_usage(MarkSweepGC._size_gc_header + size)
+            if hdr.typeid & 1:
+                hdr.typeid = hdr.typeid & (~1)
                 newmo.append(curr)
-                curr_heap_size += size + MarkSweepGC._size_gc_header
+                curr_heap_size += estimate
             else:
-                freed_size += size + MarkSweepGC._size_gc_header
+                freed_size += estimate
                 raw_free(curr)
         free_non_gc_object(self.malloced_objects)
         self.malloced_objects = newmo
@@ -246,7 +249,8 @@
         return MarkSweepGC._size_gc_header
 
     def init_gc_object(self, addr, typeid):
-        addr.signed[0] = typeid << 1
+        hdr = llmemory.cast_adr_to_ptr(addr, self.HDRPTR)
+        hdr.typeid = typeid << 1
     init_gc_object_immortal = init_gc_object
 
 class SemiSpaceGC(GCBase):

Modified: pypy/dist/pypy/rpython/memory/gctransform.py
==============================================================================
--- pypy/dist/pypy/rpython/memory/gctransform.py	(original)
+++ pypy/dist/pypy/rpython/memory/gctransform.py	Mon May 15 00:46:57 2006
@@ -878,9 +878,9 @@
         self.c_const_gc = rmodel.inputconst(r_gc, self.gcdata.gc)
 
     def build_stack_root_iterator(self):
-        rootstacksize = 640*1024    # XXX adjust
         gcdata = self.gcdata
         sizeofaddr = llmemory.sizeof(llmemory.Address)
+        rootstacksize = sizeofaddr * 163840    # XXX adjust
 
         class StackRootIterator:
             _alloc_flavor_ = 'raw'
@@ -944,7 +944,7 @@
                 if isinstance(TYPE, lltype.Struct):
                     ARRAY = TYPE._flds[TYPE._arrayfld]
                     ofs1 = llmemory.offsetof(TYPE, TYPE._arrayfld)
-                    info["ofstolength"] = ofs1
+                    info["ofstolength"] = ofs1 + llmemory.ArrayLengthOffset(ARRAY)
                     if ARRAY.OF != lltype.Void:
                         info["ofstovar"] = ofs1 + llmemory.itemoffsetof(ARRAY, 0)
                     else:

Modified: pypy/dist/pypy/rpython/memory/lladdress.py
==============================================================================
--- pypy/dist/pypy/rpython/memory/lladdress.py	(original)
+++ pypy/dist/pypy/rpython/memory/lladdress.py	Mon May 15 00:46:57 2006
@@ -121,6 +121,10 @@
 def raw_malloc(size):
     return _address(simulator.malloc(size))
 
+def raw_malloc_usage(size):
+    assert isinstance(size, int)
+    return size
+
 def raw_free(addr):
     simulator.free(addr.intaddress)
 

Modified: pypy/dist/pypy/rpython/memory/lltypelayout.py
==============================================================================
--- pypy/dist/pypy/rpython/memory/lltypelayout.py	(original)
+++ pypy/dist/pypy/rpython/memory/lltypelayout.py	Mon May 15 00:46:57 2006
@@ -93,8 +93,7 @@
         layout = get_layout(offset.TYPE)
         return layout[offset.fldname]
     elif isinstance(offset, llmemory.CompositeOffset):
-        return convert_offset_to_int(offset.first) + \
-               convert_offset_to_int(offset.second)
+        return sum([convert_offset_to_int(item) for item in offset.offsets])
     elif type(offset) == llmemory.AddressOffset:
         return 0
     elif isinstance(offset, llmemory.ItemOffset):

Modified: pypy/dist/pypy/rpython/memory/lltypesimulation.py
==============================================================================
--- pypy/dist/pypy/rpython/memory/lltypesimulation.py	(original)
+++ pypy/dist/pypy/rpython/memory/lltypesimulation.py	Mon May 15 00:46:57 2006
@@ -108,6 +108,8 @@
                                                                 field_name))
 
     def __getitem__(self, i):
+        if isinstance(self._T, lltype.FixedSizeArray):
+            return self.__getattr__('item%d' % i)
         if isinstance(self._T, lltype.Array):
             if not (0 <= i < self._address.signed[0]):
                 raise IndexError, "array index out of bounds"
@@ -116,6 +118,8 @@
         raise TypeError("%r instance is not an array" % (self._T,))
 
     def __setitem__(self, i, value):
+        if isinstance(self._T, lltype.FixedSizeArray):
+            return self.__setattr__('item%d' % i, value)
         if isinstance(self._T, lltype.Array):
             T1 = self._T.OF
             if isinstance(T1, lltype.ContainerType):

Modified: pypy/dist/pypy/rpython/memory/support.py
==============================================================================
--- pypy/dist/pypy/rpython/memory/support.py	(original)
+++ pypy/dist/pypy/rpython/memory/support.py	Mon May 15 00:46:57 2006
@@ -1,68 +1,81 @@
-from pypy.rpython.memory.lladdress import raw_malloc, raw_free, NULL
-from pypy.rpython.lltypesystem import lltype
+from pypy.rpython.lltypesystem import lltype, llmemory
 from pypy.rpython.memory.lltypelayout import sizeof
-import struct
 
 INT_SIZE = sizeof(lltype.Signed)
 
-CHUNK_SIZE = 1022
+DEFAULT_CHUNK_SIZE = 1019
 
-class FreeList(object):
-    _alloc_flavor_ = "raw"
+def get_address_linked_list(chunk_size=DEFAULT_CHUNK_SIZE):
 
-    def __init__(self, size):
-        self.free_list = NULL
-        self.size = size
-
-    def get(self):
-        if self.free_list == NULL:
-            return raw_malloc(self.size * INT_SIZE)
-        result = self.free_list
-        self.free_list = result.address[0]
-        return result
-
-    def put(self, chunk):
-        chunk.address[0] = self.free_list
-        self.free_list = chunk
+    CHUNK = lltype.ForwardReference()
+    CHUNK.become(lltype.Struct('AddressLinkedListChunk',
+                               ('previous', lltype.Ptr(CHUNK)),
+                               ('length', lltype.Signed),
+                               ('items', lltype.FixedSizeArray(
+                                   llmemory.Address, chunk_size))))
+    null_chunk = lltype.nullptr(CHUNK)
+
+    class FreeList(object):
+        _alloc_flavor_ = "raw"
+
+        def __init__(self):
+            self.free_list = null_chunk
+
+        def get(self):
+            if not self.free_list:
+                return lltype.malloc(CHUNK, flavor='raw')
+            result = self.free_list
+            self.free_list = result.previous
+            return result
+
+        def put(self, chunk):
+            chunk.previous = self.free_list
+            self.free_list = chunk
+
+    unused_chunks = FreeList()
 
-def get_address_linked_list(chunk_size=CHUNK_SIZE):
-    unused_chunks = FreeList(chunk_size + 2)
     class AddressLinkedList(object):
         _alloc_flavor_ = "raw"
         
         def __init__(self):
             self.chunk = unused_chunks.get()
-            self.chunk.address[0] = NULL
-            self.chunk.signed[1] = 0
+            self.chunk.previous = null_chunk
+            self.chunk.length = 0
 
         def append(self, addr):
-            if addr == NULL:
+            if addr == llmemory.NULL:
                 return
-            if self.chunk.signed[1] == chunk_size:
+            if self.chunk.length == chunk_size:
                 new = unused_chunks.get()
-                new.address[0] = self.chunk
-                new.signed[1] = 0
+                new.previous = self.chunk
+                new.length = 0
                 self.chunk = new
-            used_chunks = self.chunk.signed[1]
-            self.chunk.signed[1] += 1
-            self.chunk.address[used_chunks + 2] = addr
+            used_chunks = self.chunk.length
+            self.chunk.length += 1
+            self.chunk.items[used_chunks] = addr
             
         def pop(self):
-            used_chunks = self.chunk.signed[1]
+            used_chunks = self.chunk.length
             if used_chunks == 0:
                 old = self.chunk
-                previous = old.address[0]
-                if previous == NULL:
-                    return NULL
+                previous = old.previous
+                if not previous:
+                    return llmemory.NULL
                 self.chunk = previous
                 unused_chunks.put(old)
-                used_chunks = self.chunk.signed[1]
-            result = self.chunk.address[used_chunks + 1]
-            self.chunk.address[used_chunks + 1] = NULL
-            self.chunk.signed[1] = used_chunks - 1
+                used_chunks = self.chunk.length
+            result = self.chunk.items[used_chunks - 1]
+            #self.chunk.items[used_chunks - 1] = llmemory.NULL
+            self.chunk.length = used_chunks - 1
             return result
 
         def free(self):   # XXX very inefficient
-            while self.pop() != NULL:
-                pass
+            cur = self.chunk
+            while cur.previous:
+                prev = cur.previous
+                unused_chunks.put(cur)
+                cur = prev
+            self.chunk = cur
+            cur.length =  0
+
     return AddressLinkedList

Modified: pypy/dist/pypy/rpython/memory/test/test_gc.py
==============================================================================
--- pypy/dist/pypy/rpython/memory/test/test_gc.py	(original)
+++ pypy/dist/pypy/rpython/memory/test/test_gc.py	Mon May 15 00:46:57 2006
@@ -6,7 +6,7 @@
 from pypy.rpython.rtyper import RPythonTyper
 from pypy.rpython.memory.gc import GCError, MarkSweepGC, SemiSpaceGC
 from pypy.rpython.memory.gc import DeferredRefcountingGC, DummyGC
-from pypy.rpython.memory.support import INT_SIZE, CHUNK_SIZE
+from pypy.rpython.memory.support import INT_SIZE
 from pypy.rpython.memory import support
 from pypy.rpython.memory.lladdress import raw_malloc, raw_free, NULL
 from pypy.rpython.memory.simulator import MemorySimulatorError
@@ -15,9 +15,6 @@
 from pypy.rpython.memory.lladdress import simulator
 from pypy.rpython.objectmodel import free_non_gc_object
 
-import struct
-INT_SIZE = struct.calcsize("l")
-
 def setup_module(mod):
     def stdout_ignore_ll_functions(msg):
         strmsg = str(msg)

Modified: pypy/dist/pypy/rpython/memory/test/test_gctransform.py
==============================================================================
--- pypy/dist/pypy/rpython/memory/test/test_gctransform.py	(original)
+++ pypy/dist/pypy/rpython/memory/test/test_gctransform.py	Mon May 15 00:46:57 2006
@@ -701,15 +701,19 @@
     
     t = rtype(entrypoint, [s_list_of_strings])
     cbuild = CStandaloneBuilder(t, entrypoint, gc.FrameworkGcPolicy)
-    cbuild.generate_graphs_for_llinterp()
+    db = cbuild.generate_graphs_for_llinterp()
     entrypointptr = cbuild.getentrypointptr()
     entrygraph = entrypointptr._obj.graph
 
     r_list_of_strings = t.rtyper.getrepr(s_list_of_strings)
     ll_argv = r_list_of_strings.convert_const([])
 
-    py.test.skip('in-progress')
     llinterp = LLInterpreter(t.rtyper)
+    
+    # FIIIIISH
+    setupgraph = db.gctransformer.frameworkgc_setup_ptr.value._obj.graph
+    llinterp.eval_graph(setupgraph, [])
+
     res = llinterp.eval_graph(entrygraph, [ll_argv])
 
     assert ''.join(res.chars) == "2"

Modified: pypy/dist/pypy/rpython/memory/test/test_support.py
==============================================================================
--- pypy/dist/pypy/rpython/memory/test/test_support.py	(original)
+++ pypy/dist/pypy/rpython/memory/test/test_support.py	Mon May 15 00:46:57 2006
@@ -1,5 +1,5 @@
 from pypy.rpython.objectmodel import free_non_gc_object
-from pypy.rpython.memory.support import get_address_linked_list, FreeList
+from pypy.rpython.memory.support import get_address_linked_list
 from pypy.rpython.memory import support
 from pypy.rpython.memory.lladdress import raw_malloc, raw_free, NULL
 from pypy.rpython.memory.test.test_llinterpsim import interpret
@@ -53,7 +53,7 @@
         raw_free(addr)
         
 def test_linked_list_annotate():
-    AddressLinkedList = get_address_linked_list()
+    AddressLinkedList = get_address_linked_list(10)
     def f():
         addr = raw_malloc(100)
         ll = AddressLinkedList()
@@ -69,14 +69,14 @@
         res = res and (ll.pop() == NULL)
         res = res and (ll.pop() == NULL)
         ll.append(addr)
-        for i in range(3000):
+        for i in range(30):
             ll.append(addr + i)
-        for i in range(2999, -1, -1):
+        for i in range(29, -1, -1):
             a = ll.pop()
             res = res and (a - addr == i)
-        for i in range(3000):
+        for i in range(30):
             ll.append(addr + i)
-        for i in range(2999, -1, -1):
+        for i in range(29, -1, -1):
             a = ll.pop()
             res = res and (a - addr == i)
         ll.free()

Modified: pypy/dist/pypy/rpython/rbuiltin.py
==============================================================================
--- pypy/dist/pypy/rpython/rbuiltin.py	(original)
+++ pypy/dist/pypy/rpython/rbuiltin.py	Mon May 15 00:46:57 2006
@@ -500,6 +500,10 @@
     v_size, = hop.inputargs(lltype.Signed)
     return hop.genop('raw_malloc', [v_size], resulttype=llmemory.Address)
 
+def rtype_raw_malloc_usage(hop):
+    v_size, = hop.inputargs(lltype.Signed)
+    return hop.genop('raw_malloc_usage', [v_size], resulttype=lltype.Signed)
+
 def rtype_raw_free(hop):
     v_addr, = hop.inputargs(llmemory.Address)
     return hop.genop('raw_free', [v_addr])
@@ -509,6 +513,7 @@
     return hop.genop('raw_memcopy', v_list)
 
 BUILTIN_TYPER[lladdress.raw_malloc] = rtype_raw_malloc
+BUILTIN_TYPER[lladdress.raw_malloc_usage] = rtype_raw_malloc_usage
 BUILTIN_TYPER[lladdress.raw_free] = rtype_raw_free
 BUILTIN_TYPER[lladdress.raw_memcopy] = rtype_raw_memcopy
 

Modified: pypy/dist/pypy/translator/c/genc.py
==============================================================================
--- pypy/dist/pypy/translator/c/genc.py	(original)
+++ pypy/dist/pypy/translator/c/genc.py	Mon May 15 00:46:57 2006
@@ -141,6 +141,7 @@
             if isinstance(node, FuncNode):
                 for funcgen in node.funcgens:
                     funcgen.patch_graph(copy_graph=False)
+        return db
 
 
 class CExtModuleBuilder(CBuilder):

Modified: pypy/dist/pypy/translator/c/node.py
==============================================================================
--- pypy/dist/pypy/translator/c/node.py	(original)
+++ pypy/dist/pypy/translator/c/node.py	Mon May 15 00:46:57 2006
@@ -541,8 +541,8 @@
 
 class FuncNode(ContainerNode):
     nodekind = 'func'
-    if USESLOTS:
-        __slots__ = """funcgens""".split()
+    # there not so many node of this kind, slots should not
+    # be necessary
 
     def __init__(self, db, T, obj):
         self.globalcontainer = True
@@ -633,8 +633,6 @@
         del bodyiter
         funcgen.implementation_end()
 
-assert not USESLOTS or '__dict__' not in dir(FuncNode)
-
 def select_function_code_generators(fnobj, db, functionname):
     if fnobj._callable in extfunc.EXTERNALS:
         # 'fnobj' is one of the ll_xyz() functions with the suggested_primitive

Modified: pypy/dist/pypy/translator/c/primitive.py
==============================================================================
--- pypy/dist/pypy/translator/c/primitive.py	(original)
+++ pypy/dist/pypy/translator/c/primitive.py	Mon May 15 00:46:57 2006
@@ -33,7 +33,8 @@
             return 'offsetof(%s, length)'%(
                 cdecl(db.gettype(value.TYPE), ''))
         elif isinstance(value, CompositeOffset):
-            return '(%s + %s)' % (name_signed(value.first, db), name_signed(value.second, db))
+            names = [name_signed(item, db) for item in value.offsets]
+            return '(%s)' % (' + '.join(names),)
         elif type(value) == AddressOffset:
             return '0'
         elif type(value) == GCHeaderOffset:

Modified: pypy/dist/pypy/translator/c/src/address.h
==============================================================================
--- pypy/dist/pypy/translator/c/src/address.h	(original)
+++ pypy/dist/pypy/translator/c/src/address.h	Mon May 15 00:46:57 2006
@@ -20,6 +20,8 @@
     r = (void*) calloc(1, size);                                       \
     if (r == NULL) FAIL_EXCEPTION( PyExc_MemoryError, "out of memory");\
 
+#define OP_RAW_MALLOC_USAGE(size, r) r = size
+
 #ifdef MS_WINDOWS
 #define alloca  _alloca
 #endif


From arigo at codespeak.net  Mon May 15 01:17:26 2006
From: arigo at codespeak.net (arigo at codespeak.net)
Date: Mon, 15 May 2006 01:17:26 +0200 (CEST)
Subject: [pypy-svn] r27212 - pypy/dist/pypy/rpython/lltypesystem
Message-ID: <20060514231726.EEEBB100B6@code0.codespeak.net>

Author: arigo
Date: Mon May 15 01:17:24 2006
New Revision: 27212

Modified:
   pypy/dist/pypy/rpython/lltypesystem/llmemory.py
Log:
A last fix and XXX for tonight.


Modified: pypy/dist/pypy/rpython/lltypesystem/llmemory.py
==============================================================================
--- pypy/dist/pypy/rpython/lltypesystem/llmemory.py	(original)
+++ pypy/dist/pypy/rpython/lltypesystem/llmemory.py	Mon May 15 01:17:24 2006
@@ -284,6 +284,7 @@
 
 class fakeaddress(object):
     def __init__(self, ob, offset=None):
+        #assert not isinstance(ob, lltype._parentable) - XXX in-progress
         self.ob = ob or None    # replace null pointers with None
         self.offset = offset
 
@@ -422,7 +423,7 @@
     def convert(self, value):
         if isinstance(value, lltype._ptr):
             return fakeaddress(value)
-        elif isinstance(value, Address):
+        elif lltype.typeOf(value) == Address:
             return value
         else:
             raise TypeError(value)


From hpk at codespeak.net  Mon May 15 10:40:32 2006
From: hpk at codespeak.net (hpk at codespeak.net)
Date: Mon, 15 May 2006 10:40:32 +0200 (CEST)
Subject: [pypy-svn] r27217 - pypy/extradoc/sprintinfo/ddorf2006
Message-ID: <20060515084032.8982F10092@code0.codespeak.net>

Author: hpk
Date: Mon May 15 10:40:26 2006
New Revision: 27217

Modified:
   pypy/extradoc/sprintinfo/ddorf2006/announce.txt
Log:
little tweaks to the announcement, should go out, shouldn't it? 


Modified: pypy/extradoc/sprintinfo/ddorf2006/announce.txt
==============================================================================
--- pypy/extradoc/sprintinfo/ddorf2006/announce.txt	(original)
+++ pypy/extradoc/sprintinfo/ddorf2006/announce.txt	Mon May 15 10:40:26 2006
@@ -26,8 +26,8 @@
 
 If you'd like to come, please subscribe to the `pypy-sprint mailing list`_
 and drop a note about your interests and post any questions.  More 
-(organisational) information will be send to that list.  We'll keep
-a list of `people`_ which we'll update (or you can do so yourself
+organisational information will be send to that list.  We'll keep
+a list of `people`_ which we'll update (which you can do so yourself
 if you codespeak commit rights). 
 
 .. _`pypy-sprint mailing list`: http://codespeak.net/mailman/listinfo/pypy-sprint


From pypy-dev-owner at codespeak.net  Mon May 15 12:37:31 2006
From: pypy-dev-owner at codespeak.net (Genaro)
Date: Mon, 15 May 2006 01:37:31 -0900
Subject: [pypy-svn] I test these p1lls it's amazing!
Message-ID: <57773229.20060515013731@codespeak.net>

An HTML attachment was scrubbed...
URL: 

From mwh at codespeak.net  Mon May 15 10:44:00 2006
From: mwh at codespeak.net (mwh at codespeak.net)
Date: Mon, 15 May 2006 10:44:00 +0200 (CEST)
Subject: [pypy-svn] r27218 - in pypy/dist/pypy: annotation rpython/test
Message-ID: <20060515084400.B3BA3100B6@code0.codespeak.net>

Author: mwh
Date: Mon May 15 10:43:59 2006
New Revision: 27218

Modified:
   pypy/dist/pypy/annotation/builtin.py
   pypy/dist/pypy/rpython/test/test_llann.py
Log:
fix translation, by weakening an overstrong assert.


Modified: pypy/dist/pypy/annotation/builtin.py
==============================================================================
--- pypy/dist/pypy/annotation/builtin.py	(original)
+++ pypy/dist/pypy/annotation/builtin.py	Mon May 15 10:43:59 2006
@@ -376,7 +376,7 @@
 from pypy.rpython.lltypesystem import lltype
 
 def malloc(T, n=None, s_flavor=None):
-    assert n is None or n.knowntype == int
+    assert n is None or (n.knowntype == int or issubclass(n.knowntype, pypy.rpython.rarithmetic.base_int))
     assert T.is_constant()
     if n is not None:
         n = 1

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 May 15 10:43:59 2006
@@ -53,6 +53,16 @@
         s = self.annotate(llf, [])
         assert s.knowntype == int
 
+    def test_array_longlong(self):
+        from pypy.rpython.rarithmetic import r_longlong
+        A = GcArray(('v', Signed))
+        one = r_longlong(1)
+        def llf():
+            a = malloc(A, one)
+            return a[0].v
+        s = self.annotate(llf, [])
+        assert s.knowntype == int
+
     def test_prim_array(self):
         A = GcArray(Signed)
         def llf():


From cfbolz at codespeak.net  Mon May 15 10:46:03 2006
From: cfbolz at codespeak.net (cfbolz at codespeak.net)
Date: Mon, 15 May 2006 10:46:03 +0200 (CEST)
Subject: [pypy-svn] r27219 - pypy/extradoc/sprintinfo/ddorf2006
Message-ID: <20060515084603.66686100BD@code0.codespeak.net>

Author: cfbolz
Date: Mon May 15 10:45:59 2006
New Revision: 27219

Modified:
   pypy/extradoc/sprintinfo/ddorf2006/people.txt
Log:
add me to people list


Modified: pypy/extradoc/sprintinfo/ddorf2006/people.txt
==============================================================================
--- pypy/extradoc/sprintinfo/ddorf2006/people.txt	(original)
+++ pypy/extradoc/sprintinfo/ddorf2006/people.txt	Mon May 15 10:45:59 2006
@@ -11,6 +11,7 @@
 Michael Hudson       ?              private
 Armin Rigo           ?              private
 Holger Krekel        2nd-9th        ?
+Carl Friedrich Bolz  nope :-)       private
 ==================== ============== =====================
 
 People on the following list were present at previous sprints: 
@@ -35,7 +36,6 @@
 Laura Creighton      ?              ?
 Beatrice Duering     ?              ?
 Eric van Riet Paap   ?              ?
-Carl Friedrich Bolz  ?              ?
 Richard Emslie       ?              ?
 Johan Hahn           ?              ?
 ==================== ============== =====================


From arigo at codespeak.net  Mon May 15 10:51:59 2006
From: arigo at codespeak.net (arigo at codespeak.net)
Date: Mon, 15 May 2006 10:51:59 +0200 (CEST)
Subject: [pypy-svn] r27221 - pypy/extradoc/sprintinfo/ddorf2006
Message-ID: <20060515085159.7AAF7100B6@code0.codespeak.net>

Author: arigo
Date: Mon May 15 10:51:58 2006
New Revision: 27221

Modified:
   pypy/extradoc/sprintinfo/ddorf2006/announce.txt
Log:
Typo.


Modified: pypy/extradoc/sprintinfo/ddorf2006/announce.txt
==============================================================================
--- pypy/extradoc/sprintinfo/ddorf2006/announce.txt	(original)
+++ pypy/extradoc/sprintinfo/ddorf2006/announce.txt	Mon May 15 10:51:58 2006
@@ -28,7 +28,7 @@
 and drop a note about your interests and post any questions.  More 
 organisational information will be send to that list.  We'll keep
 a list of `people`_ which we'll update (which you can do so yourself
-if you codespeak commit rights). 
+if you have codespeak commit rights). 
 
 .. _`pypy-sprint mailing list`: http://codespeak.net/mailman/listinfo/pypy-sprint
 .. _`people`: http://codespeak.net/pypy/extradoc/sprintinfo/ddorf2006/people.html


From antocuni at codespeak.net  Mon May 15 10:59:13 2006
From: antocuni at codespeak.net (antocuni at codespeak.net)
Date: Mon, 15 May 2006 10:59:13 +0200 (CEST)
Subject: [pypy-svn] r27222 - pypy/dist/pypy/rpython/ootypesystem
Message-ID: <20060515085913.6C1CA10093@code0.codespeak.net>

Author: antocuni
Date: Mon May 15 10:59:02 2006
New Revision: 27222

Modified:
   pypy/dist/pypy/rpython/ootypesystem/ootype.py
   pypy/dist/pypy/rpython/ootypesystem/rstr.py
Log:
Automatic generation of some boilerplate in ootypestem.rstr.LLHelpers.



Modified: pypy/dist/pypy/rpython/ootypesystem/ootype.py
==============================================================================
--- pypy/dist/pypy/rpython/ootypesystem/ootype.py	(original)
+++ pypy/dist/pypy/rpython/ootypesystem/ootype.py	Mon May 15 10:59:02 2006
@@ -820,9 +820,11 @@
         return cmp(self._str, s._str)
 
     def ll_startswith(self, s):
+        # NOT_RPYTHON
         return self._str.startswith(s._str)
 
     def ll_endswith(self, s):
+        # NOT_RPYTHON
         return self._str.endswith(s._str)
 
     # delegate missing ll_* methods to self._str
@@ -834,8 +836,8 @@
 
     @staticmethod
     def wrapper(fn):
-        def f(*args, **kwds):
-            res = fn(*args, **kwds)
+        def f(*args):
+            res = fn(*args)
             if isinstance(res, str):
                 return make_string(res)
             elif isinstance(res, list):

Modified: pypy/dist/pypy/rpython/ootypesystem/rstr.py
==============================================================================
--- pypy/dist/pypy/rpython/ootypesystem/rstr.py	(original)
+++ pypy/dist/pypy/rpython/ootypesystem/rstr.py	Mon May 15 10:59:02 2006
@@ -51,14 +51,12 @@
     lowleveltype = UniChar
 
 class LLHelpers(AbstractLLHelpers):
-    def ll_stritem_nonneg(s, i):
-        return s.ll_stritem_nonneg(i)
-
-    def ll_strlen(s):
-        return s.ll_strlen()
-
-    def ll_strconcat(s1, s2):
-        return s1.ll_strconcat(s2)
+##    METHODS = ['ll_stritem_nonneg',
+##               'll_strlen',
+##               'll_strconcat',
+##               'll_startswith',
+##               'll_endswith',
+##               ]
 
     def ll_chr2str(ch):
         return ootype.oostring(ch)
@@ -84,12 +82,23 @@
             return False
         return s1.ll_strcmp(s2)
 
-    def ll_startswith(s1, s2):
-        return s1.ll_startswith(s2)
+def add_helpers():
+    dic = {}
+    for name, meth in ootype.String._GENERIC_METHODS.iteritems():
+        if name in LLHelpers.__dict__:
+            continue
+        n_args = len(meth.ARGS)
+        args = ', '.join('arg%d' % i for i in range(n_args))
+        code = """
+def %s(obj, %s):
+    return obj.%s(%s)
+""" % (name, args, name, args)
+        exec code in dic
+        setattr(LLHelpers, name, staticmethod(dic[name]))
+
+add_helpers()
+del add_helpers
 
-    def ll_endswith(s1, s2):
-        return s1.ll_endswith(s2)
-    
 
 string_repr = StringRepr()
 char_repr = CharRepr()


From ericvrp at codespeak.net  Mon May 15 12:46:52 2006
From: ericvrp at codespeak.net (ericvrp at codespeak.net)
Date: Mon, 15 May 2006 12:46:52 +0200 (CEST)
Subject: [pypy-svn] r27228 - pypy/extradoc/sprintinfo/ddorf2006
Message-ID: <20060515104652.CC43B1009A@code0.codespeak.net>

Author: ericvrp
Date: Mon May 15 12:46:51 2006
New Revision: 27228

Modified:
   pypy/extradoc/sprintinfo/ddorf2006/people.txt
Log:
Will come to dusseldorf some of the days.


Modified: pypy/extradoc/sprintinfo/ddorf2006/people.txt
==============================================================================
--- pypy/extradoc/sprintinfo/ddorf2006/people.txt	(original)
+++ pypy/extradoc/sprintinfo/ddorf2006/people.txt	Mon May 15 12:46:51 2006
@@ -12,6 +12,7 @@
 Armin Rigo           ?              private
 Holger Krekel        2nd-9th        ?
 Carl Friedrich Bolz  nope :-)       private
+Eric van Riet Paap   ?              ?
 ==================== ============== =====================
 
 People on the following list were present at previous sprints: 
@@ -35,7 +36,6 @@
 Bert Freudenberg     ?              ?
 Laura Creighton      ?              ?
 Beatrice Duering     ?              ?
-Eric van Riet Paap   ?              ?
 Richard Emslie       ?              ?
 Johan Hahn           ?              ?
 ==================== ============== =====================


From mwh at codespeak.net  Mon May 15 13:08:00 2006
From: mwh at codespeak.net (mwh at codespeak.net)
Date: Mon, 15 May 2006 13:08:00 +0200 (CEST)
Subject: [pypy-svn] r27229 - in pypy/dist/pypy/translator/stackless: . test
Message-ID: <20060515110800.0DB79100B6@code0.codespeak.net>

Author: mwh
Date: Mon May 15 13:07:58 2006
New Revision: 27229

Modified:
   pypy/dist/pypy/translator/stackless/test/test_transform.py
   pypy/dist/pypy/translator/stackless/transform.py
Log:
convert a few stackless tests to say "rstack.stack_unwind" instead of "raise
code.UnwindException" which lets me simplify the detection of a function that
might unwind the stack.


Modified: pypy/dist/pypy/translator/stackless/test/test_transform.py
==============================================================================
--- pypy/dist/pypy/translator/stackless/test/test_transform.py	(original)
+++ pypy/dist/pypy/translator/stackless/test/test_transform.py	Mon May 15 13:07:58 2006
@@ -5,7 +5,7 @@
 from pypy.translator.c import gc
 from pypy.rpython.memory.gctransform import varoftype
 from pypy.rpython.lltypesystem import lltype, llmemory
-from pypy.rpython import llinterp
+from pypy.rpython import llinterp, rstack
 from pypy.translator.translator import TranslationContext, graphof
 from pypy.objspace.flow.model import checkgraph
 from pypy.annotation import model as annmodel
@@ -34,8 +34,6 @@
 
     assert s2_1 is s2_2
 
-from pypy.translator.stackless import code
-
 def factorial(n):
     if n > 1:
         return factorial(n-1) * n
@@ -55,8 +53,7 @@
 def test_simple_transform_llinterp():
     def check(x):
         if x:
-            raise code.UnwindException
-    check.stackless_explicit = True
+            rstack.stack_unwind()
     def g(x):
         check(x)
         return x + 1
@@ -68,7 +65,7 @@
 def test_simple_transform_llinterp_float():
     def check(x):
         if x:
-            raise code.UnwindException
+            rstack.stack_unwind()
     def g(x):
         check(x)
         return x + 0.125
@@ -80,7 +77,7 @@
 def test_simple_transform_compiled():
     def check(x):
         if x:
-            raise code.UnwindException # XXX or so
+            rstack.stack_unwind()
     def g(x):
         check(x)
         return x + 1
@@ -92,7 +89,7 @@
 def test_protected_call():
     def check(x):
         if x:
-            raise code.UnwindException
+            rstack.stack_unwind()
     def g(x):
         check(x)
         return x + 1
@@ -110,7 +107,7 @@
 def test_resume_with_exception():
     def check(x):
         if x:
-            raise code.UnwindException
+            rstack.stack_unwind()
     def g(x):
         check(x)
         if x:
@@ -130,7 +127,7 @@
 def test_resume_with_exception_handling():
     def check(x):
         if x:
-            raise code.UnwindException
+            rstack.stack_unwind()
     def g(x):
         check(x)
         if x:
@@ -151,7 +148,7 @@
 def test_resume_with_exception_handling_with_vals():
     def check(x):
         if x:
-            raise code.UnwindException
+            rstack.stack_unwind()
     def g(x):
         check(x)
         if x:
@@ -173,8 +170,7 @@
 def test_listcomp():
     def check(x):
         if x:
-            raise code.UnwindException
-    check.stackless_explicit = True
+            rstack.stack_unwind()
     def f():
         l = one()
         check(l)
@@ -208,8 +204,7 @@
 def test_dont_transform_too_much():
     def check(x):
         if x:
-            raise code.UnwindException
-    check.stackless_explicit = True
+            rstack.stack_unwind()
     def f(x):
         return x + 2
     def g(x):

Modified: pypy/dist/pypy/translator/stackless/transform.py
==============================================================================
--- pypy/dist/pypy/translator/stackless/transform.py	(original)
+++ pypy/dist/pypy/translator/stackless/transform.py	Mon May 15 13:07:58 2006
@@ -101,15 +101,6 @@
                 self.stackless_gc and (op.opname.startswith('malloc')
                                        or op.opname == 'gc__collect'))
 
-    def analyze_link(self, graph, link):
-        if link.target is graph.exceptblock:
-            # XXX is this the right way to do this?
-            op = link.prevblock.operations[-1]
-            if op.opname == 'cast_pointer':
-                ct = op.args[0].concretetype
-                return ct is self.unwindtype
-        return False
-
     def analyze_external_call(self, op):
         callable = op.args[0].value._obj._callable
         #assert getattr(callable, 'suggested_primitive', False)


From mwh at codespeak.net  Mon May 15 13:27:54 2006
From: mwh at codespeak.net (mwh at codespeak.net)
Date: Mon, 15 May 2006 13:27:54 +0200 (CEST)
Subject: [pypy-svn] r27230 - in pypy/dist/pypy/translator/stackless: . test
Message-ID: <20060515112754.D6C09100B6@code0.codespeak.net>

Author: mwh
Date: Mon May 15 13:27:53 2006
New Revision: 27230

Modified:
   pypy/dist/pypy/translator/stackless/test/test_transform.py
   pypy/dist/pypy/translator/stackless/transform.py
Log:
give the stackless transformer a mode that allows the tests to assert that a
test actually tests something.  make test_constant_on_link actually test
something.


Modified: pypy/dist/pypy/translator/stackless/test/test_transform.py
==============================================================================
--- pypy/dist/pypy/translator/stackless/test/test_transform.py	(original)
+++ pypy/dist/pypy/translator/stackless/test/test_transform.py	Mon May 15 13:27:53 2006
@@ -47,8 +47,12 @@
 def test_nothing():
     def fn():
         return 21
-    res = llinterp_stackless_function(fn)
+    res = llinterp_stackless_function(fn, assert_unwind=False)
     assert res == 21
+    info = py.test.raises(
+        llinterp.LLException,
+        "llinterp_stackless_function(fn, assert_unwind=True)")
+    assert ''.join(info.value.args[0].name).strip('\x00') == "AssertionError"        
 
 def test_simple_transform_llinterp():
     def check(x):
@@ -185,6 +189,7 @@
         if m > 100:
             raise KeyError
         a = A()
+        rstack.stack_unwind()
         a.m = m + 5
         return a
     def g(n, m):
@@ -255,11 +260,12 @@
     res = cbuilder.cmdexec('')
     return int(res.strip())
 
-def llinterp_stackless_function(fn, returntranslator=False):
+def llinterp_stackless_function(fn, returntranslator=False,
+                                assert_unwind=True):
     def wrapper(argv):
         return fn()
     t = rtype_stackless_function(wrapper)
-    st = StacklessTransformer(t, wrapper)
+    st = StacklessTransformer(t, wrapper, assert_unwind=assert_unwind)
     st.transform_all()
     if conftest.option.view:
         t.view()

Modified: pypy/dist/pypy/translator/stackless/transform.py
==============================================================================
--- pypy/dist/pypy/translator/stackless/transform.py	(original)
+++ pypy/dist/pypy/translator/stackless/transform.py	Mon May 15 13:27:53 2006
@@ -111,7 +111,8 @@
 
 class StacklessTransformer(object):
 
-    def __init__(self, translator, entrypoint, stackless_gc=False):
+    def __init__(self, translator, entrypoint,
+                 stackless_gc=False, assert_unwind=False):
         self.translator = translator
         self.stackless_gc = stackless_gc
 
@@ -138,14 +139,26 @@
         mixlevelannotator = MixLevelHelperAnnotator(translator.rtyper)
         l2a = annmodel.lltype_to_annotation
 
-        def slp_entry_point(argv):
-            try:
-                r = entrypoint(argv)
-            except code.UnwindException, u:
-                code.slp_main_loop()
-                return code.global_state.retval_long
-            return r
-        slp_entry_point.stackless_explicit = True
+        if assert_unwind:
+            def slp_entry_point(argv):
+                try:
+                    r = entrypoint(argv)
+                except code.UnwindException, u:
+                    code.slp_main_loop()
+                    return code.global_state.retval_long
+                else:
+                    assert False, "entrypoint never unwound the stack"
+                return r
+            slp_entry_point.stackless_explicit = True
+        else:
+            def slp_entry_point(argv):
+                try:
+                    r = entrypoint(argv)
+                except code.UnwindException, u:
+                    code.slp_main_loop()
+                    return code.global_state.retval_long
+                return r
+            slp_entry_point.stackless_explicit = True
 
         self.slp_entry_point = slp_entry_point
         oldgraph = bk.getdesc(entrypoint).getuniquegraph()


From antocuni at codespeak.net  Mon May 15 13:50:47 2006
From: antocuni at codespeak.net (antocuni at codespeak.net)
Date: Mon, 15 May 2006 13:50:47 +0200 (CEST)
Subject: [pypy-svn] r27231 - in pypy/dist/pypy/rpython: . ootypesystem
Message-ID: <20060515115047.166D910093@code0.codespeak.net>

Author: antocuni
Date: Mon May 15 13:50:40 2006
New Revision: 27231

Modified:
   pypy/dist/pypy/rpython/ootypesystem/ootype.py
   pypy/dist/pypy/rpython/ootypesystem/rstr.py
   pypy/dist/pypy/rpython/rstr.py
Log:
Python2.3-ify



Modified: pypy/dist/pypy/rpython/ootypesystem/ootype.py
==============================================================================
--- pypy/dist/pypy/rpython/ootypesystem/ootype.py	(original)
+++ pypy/dist/pypy/rpython/ootypesystem/ootype.py	Mon May 15 13:50:40 2006
@@ -834,7 +834,6 @@
         else:
             raise AttributeError, attr
 
-    @staticmethod
     def wrapper(fn):
         def f(*args):
             res = fn(*args)
@@ -850,6 +849,7 @@
             else:
                 return res
         return f
+    wrapper = staticmethod(wrapper)
 
 class _null_string(_null_mixin(_string), _string):
     def __init__(self, STRING):

Modified: pypy/dist/pypy/rpython/ootypesystem/rstr.py
==============================================================================
--- pypy/dist/pypy/rpython/ootypesystem/rstr.py	(original)
+++ pypy/dist/pypy/rpython/ootypesystem/rstr.py	Mon May 15 13:50:40 2006
@@ -51,12 +51,6 @@
     lowleveltype = UniChar
 
 class LLHelpers(AbstractLLHelpers):
-##    METHODS = ['ll_stritem_nonneg',
-##               'll_strlen',
-##               'll_strconcat',
-##               'll_startswith',
-##               'll_endswith',
-##               ]
 
     def ll_chr2str(ch):
         return ootype.oostring(ch)
@@ -88,7 +82,7 @@
         if name in LLHelpers.__dict__:
             continue
         n_args = len(meth.ARGS)
-        args = ', '.join('arg%d' % i for i in range(n_args))
+        args = ', '.join(['arg%d' % i for i in range(n_args)])
         code = """
 def %s(obj, %s):
     return obj.%s(%s)

Modified: pypy/dist/pypy/rpython/rstr.py
==============================================================================
--- pypy/dist/pypy/rpython/rstr.py	(original)
+++ pypy/dist/pypy/rpython/rstr.py	Mon May 15 13:50:40 2006
@@ -517,24 +517,23 @@
     def ll_unichar_hash(ch):
         return ord(ch)
 
-    @classmethod
     def ll_str_is_true(cls, s):
         # check if a string is True, allowing for None
         return bool(s) and cls.ll_strlen(s) != 0
+    ll_str_is_true = classmethod(ll_str_is_true)
 
-    @classmethod
     def ll_stritem_nonneg_checked(cls, s, i):
         if i >= cls.ll_strlen(s):
             raise IndexError
         return cls.ll_stritem_nonneg(s, i)
+    ll_stritem_nonneg_checked = classmethod(ll_stritem_nonneg_checked)
 
-    @classmethod
     def ll_stritem(cls, s, i):
         if i < 0:
             i += cls.ll_strlen(s)
         return cls.ll_stritem_nonneg(s, i)
+    ll_stritem = classmethod(ll_stritem)
 
-    @classmethod
     def ll_stritem_checked(cls, s, i):
         length = cls.ll_strlen(s)
         if i < 0:
@@ -542,4 +541,4 @@
         if i >= length or i < 0:
             raise IndexError
         return cls.ll_stritem_nonneg(s, i)
-
+    ll_stritem_checked = classmethod(ll_stritem_checked)


From antocuni at codespeak.net  Mon May 15 13:57:29 2006
From: antocuni at codespeak.net (antocuni at codespeak.net)
Date: Mon, 15 May 2006 13:57:29 +0200 (CEST)
Subject: [pypy-svn] r27232 - in pypy/dist/pypy/rpython/ootypesystem: . test
Message-ID: <20060515115729.DFAF510093@code0.codespeak.net>

Author: antocuni
Date: Mon May 15 13:57:24 2006
New Revision: 27232

Modified:
   pypy/dist/pypy/rpython/ootypesystem/ootype.py
   pypy/dist/pypy/rpython/ootypesystem/test/test_oostring.py
Log:
Removed the __getattr__ trick from ootype._string because it didn't
work with the annotator.



Modified: pypy/dist/pypy/rpython/ootypesystem/ootype.py
==============================================================================
--- pypy/dist/pypy/rpython/ootypesystem/ootype.py	(original)
+++ pypy/dist/pypy/rpython/ootypesystem/ootype.py	Mon May 15 13:57:24 2006
@@ -827,30 +827,6 @@
         # NOT_RPYTHON
         return self._str.endswith(s._str)
 
-    # delegate missing ll_* methods to self._str
-    def __getattr__(self, attr):
-        if attr.startswith('ll_'):
-            return self.wrapper(getattr(self._str, attr[3:]))
-        else:
-            raise AttributeError, attr
-
-    def wrapper(fn):
-        def f(*args):
-            res = fn(*args)
-            if isinstance(res, str):
-                return make_string(res)
-            elif isinstance(res, list):
-                # it must be a list of strings
-                for i, item in enumerate(res):
-                    res[i] = make_string(item)
-                lst = _list(List(String))
-                lst._list = res
-                return lst
-            else:
-                return res
-        return f
-    wrapper = staticmethod(wrapper)
-
 class _null_string(_null_mixin(_string), _string):
     def __init__(self, STRING):
         self.__dict__["_TYPE"] = STRING

Modified: pypy/dist/pypy/rpython/ootypesystem/test/test_oostring.py
==============================================================================
--- pypy/dist/pypy/rpython/ootypesystem/test/test_oostring.py	(original)
+++ pypy/dist/pypy/rpython/ootypesystem/test/test_oostring.py	Mon May 15 13:57:24 2006
@@ -7,18 +7,6 @@
     res = interpret(f, [], type_system="ootype")
     assert res._str == "foo"
 
-def test_builtin_method():
-    s = ootype.make_string('foo bar')
-    assert s.ll_startswith('foo') == True
-    assert s.ll_upper()._str == 'FOO BAR'
-
-def test_split():
-    s = ootype.make_string('foo bar')
-    res = s.ll_split()
-    assert isinstance(res, ootype._list)
-    assert res.ll_getitem_fast(0)._str == 'foo'
-    assert res.ll_getitem_fast(1)._str == 'bar'
-
 def test_string_builder():
     b = ootype.new(ootype.StringBuilder)
     b.ll_append_char('a')


From antocuni at codespeak.net  Mon May 15 14:17:49 2006
From: antocuni at codespeak.net (antocuni at codespeak.net)
Date: Mon, 15 May 2006 14:17:49 +0200 (CEST)
Subject: [pypy-svn] r27233 - in pypy/dist/pypy/rpython: ootypesystem test
Message-ID: <20060515121749.10255100A4@code0.codespeak.net>

Author: antocuni
Date: Mon May 15 14:17:42 2006
New Revision: 27233

Modified:
   pypy/dist/pypy/rpython/ootypesystem/ootype.py
   pypy/dist/pypy/rpython/test/test_rstr.py
Log:
Added support for methods find, rfind, strip, upper and lower to
ootypesystem rstr.



Modified: pypy/dist/pypy/rpython/ootypesystem/ootype.py
==============================================================================
--- pypy/dist/pypy/rpython/ootypesystem/ootype.py	(original)
+++ pypy/dist/pypy/rpython/ootypesystem/ootype.py	Mon May 15 14:17:42 2006
@@ -281,8 +281,15 @@
             "ll_streq": Meth([self.SELFTYPE_T], Bool),
             "ll_strcmp": Meth([self.SELFTYPE_T], Signed),
             "ll_startswith": Meth([self.SELFTYPE_T], Bool),
-            "ll_endswith": Meth([self.SELFTYPE_T], Bool),            
-        })
+            "ll_endswith": Meth([self.SELFTYPE_T], Bool),
+            "ll_find": Meth([self.SELFTYPE_T, Signed, Signed], Signed),
+            "ll_rfind": Meth([self.SELFTYPE_T, Signed, Signed], Signed),
+            "ll_find_char": Meth([Char, Signed, Signed], Signed),
+            "ll_rfind_char": Meth([Char, Signed, Signed], Signed),
+            "ll_strip": Meth([Char, Bool, Bool], self.SELFTYPE_T),
+            "ll_upper": Meth([], self.SELFTYPE_T),
+            "ll_lower": Meth([], self.SELFTYPE_T),
+            })
         self._setup_methods(generic_types)
 
     # TODO: should it return _null or ''?
@@ -827,6 +834,40 @@
         # NOT_RPYTHON
         return self._str.endswith(s._str)
 
+    def ll_find(self, s, start, end):
+        # NOT_RPYTHON
+        return self._str.find(s._str, start, end)
+
+    def ll_rfind(self, s, start, end):
+        # NOT_RPYTHON
+        return self._str.rfind(s._str, start, end)
+
+    def ll_find_char(self, ch, start, end):
+        # NOT_RPYTHON
+        return self._str.find(ch, start, end)
+
+    def ll_rfind_char(self, ch, start, end):
+        # NOT_RPYTHON
+        return self._str.rfind(ch, start, end)
+
+    def ll_strip(self, ch, left, right):
+        # NOT_RPYTHON
+        s = self._str
+        if left:
+            s = s.lstrip(ch)
+        if right:
+            s = s.rstrip(ch)
+        return make_string(s)
+
+    def ll_upper(self):
+        # NOT_RPYTHON
+        return make_string(self._str.upper())
+
+    def ll_lower(self):
+        # NOT_RPYTHON
+        return make_string(self._str.lower())
+
+
 class _null_string(_null_mixin(_string), _string):
     def __init__(self, STRING):
         self.__dict__["_TYPE"] = STRING

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	Mon May 15 14:17:42 2006
@@ -249,79 +249,81 @@
                 res = self.interpret(fn, [i,j])
                 assert res is fn(i, j)
 
-def test_find():
-    def fn(i, j):
-        s1 = ['one two three', 'abc abcdab abcdabcdabde']
-        s2 = ['one', 'two', 'abcdab', 'one tou', 'abcdefgh', 'fortytwo', '']
-        return s1[i].find(s2[j])
-    for i in range(2):
-        for j in range(7):
-            res = interpret(fn, [i,j])
-            assert res == fn(i, j)
-
-def test_find_with_start():
-    def fn(i):
-        assert i >= 0
-        return 'ababcabc'.find('abc', i)
-    for i in range(9):
-        res = interpret(fn, [i])
-        assert res == fn(i)
-
-def test_find_with_start_end():
-    def fn(i, j):
-        assert i >= 0
-        assert j >= 0
-        return 'ababcabc'.find('abc', i, j)
-    for (i, j) in [(1,7), (2,6), (3,7), (3,8)]:
-        res = interpret(fn, [i, j])
-        assert res == fn(i, j)
+    def test_find(self):
+        def fn(i, j):
+            s1 = ['one two three', 'abc abcdab abcdabcdabde']
+            s2 = ['one', 'two', 'abcdab', 'one tou', 'abcdefgh', 'fortytwo', '']
+            return s1[i].find(s2[j])
+        for i in range(2):
+            for j in range(7):
+                res = self.interpret(fn, [i,j])
+                assert res == fn(i, j)
 
-def test_rfind():
-    def fn():
-        return 'aaa'.rfind('a') + 'aaa'.rfind('a', 1) + 'aaa'.rfind('a', 1, 2)
-    res = interpret(fn, [])
-    assert res == 2 + 2 + 1
-
-def test_find_char():
-    def fn(ch):
-        pos1 = 'aiuwraz 483'.find(ch)
-        pos2 = 'aiuwraz 483'.rfind(ch)
-        return pos1 + (pos2*100)
-    for ch in 'a ?3':
-        res = interpret(fn, [ch])
-        assert res == fn(ch)
-
-def test_strip():
-    def both():
-        return '!ab!'.strip('!')
-    def left():
-        return '!ab!'.lstrip('!')
-    def right():
-        return '!ab!'.rstrip('!')
-    res = interpret(both, [])
-    assert ''.join(res.chars) == 'ab'
-    res = interpret(left, [])
-    assert ''.join(res.chars) == 'ab!'
-    res = interpret(right, [])
-    assert ''.join(res.chars) == '!ab'
-
-def test_upper():
-    strings = ['', ' ', 'upper', 'UpPeR', ',uppEr,']
-    for i in range(256): strings.append(chr(i))
-    def fn(i):
-        return strings[i].upper()
-    for i in range(len(strings)):
-        res = interpret(fn, [i])
-        assert ''.join(res.chars) == fn(i)
+    def test_find_with_start(self):
+        self._skip_oo('assert')
+        def fn(i):
+            assert i >= 0
+            return 'ababcabc'.find('abc', i)
+        for i in range(9):
+            res = self.interpret(fn, [i])
+            assert res == fn(i)
+
+    def test_find_with_start_end(self):
+        self._skip_oo('assert')
+        def fn(i, j):
+            assert i >= 0
+            assert j >= 0
+            return 'ababcabc'.find('abc', i, j)
+        for (i, j) in [(1,7), (2,6), (3,7), (3,8)]:
+            res = self.interpret(fn, [i, j])
+            assert res == fn(i, j)
 
-def test_lower():
-    strings = ['', ' ', 'lower', 'LoWeR', ',lowEr,']
-    for i in range(256): strings.append(chr(i))
-    def fn(i):
-        return strings[i].lower()
-    for i in range(len(strings)):
-        res = interpret(fn, [i])
-        assert ''.join(res.chars) == fn(i)
+    def test_rfind(self):
+        def fn():
+            return 'aaa'.rfind('a') + 'aaa'.rfind('a', 1) + 'aaa'.rfind('a', 1, 2)
+        res = self.interpret(fn, [])
+        assert res == 2 + 2 + 1
+
+    def test_find_char(self):
+        def fn(ch):
+            pos1 = 'aiuwraz 483'.find(ch)
+            pos2 = 'aiuwraz 483'.rfind(ch)
+            return pos1 + (pos2*100)
+        for ch in 'a ?3':
+            res = self.interpret(fn, [ch])
+            assert res == fn(ch)
+
+    def test_strip(self):
+        def both():
+            return '!ab!'.strip('!')
+        def left():
+            return '!ab!'.lstrip('!')
+        def right():
+            return '!ab!'.rstrip('!')
+        res = self.interpret(both, [])
+        assert self.ll_to_string(res) == 'ab'
+        res = self.interpret(left, [])
+        assert self.ll_to_string(res) == 'ab!'
+        res = self.interpret(right, [])
+        assert self.ll_to_string(res) == '!ab'
+
+    def test_upper(self):
+        strings = ['', ' ', 'upper', 'UpPeR', ',uppEr,']
+        for i in range(256): strings.append(chr(i))
+        def fn(i):
+            return strings[i].upper()
+        for i in range(len(strings)):
+            res = self.interpret(fn, [i])
+            assert self.ll_to_string(res) == fn(i)
+
+    def test_lower(self):
+        strings = ['', ' ', 'lower', 'LoWeR', ',lowEr,']
+        for i in range(256): strings.append(chr(i))
+        def fn(i):
+            return strings[i].lower()
+        for i in range(len(strings)):
+            res = self.interpret(fn, [i])
+            assert self.ll_to_string(res) == fn(i)
 
 def test_join():
     res = interpret(lambda: ''.join([]), [])


From ac at codespeak.net  Mon May 15 14:31:16 2006
From: ac at codespeak.net (ac at codespeak.net)
Date: Mon, 15 May 2006 14:31:16 +0200 (CEST)
Subject: [pypy-svn] r27234 - in pypy/dist/pypy/rpython/rctypes: . test
Message-ID: <20060515123116.A81EC10093@code0.codespeak.net>

Author: ac
Date: Mon May 15 14:31:16 2006
New Revision: 27234

Modified:
   pypy/dist/pypy/rpython/rctypes/rchar_p.py
   pypy/dist/pypy/rpython/rctypes/test/test_rchar_p.py
Log:
Fix NULL-ponter dereference.

Modified: pypy/dist/pypy/rpython/rctypes/rchar_p.py
==============================================================================
--- pypy/dist/pypy/rpython/rctypes/rchar_p.py	(original)
+++ pypy/dist/pypy/rpython/rctypes/rchar_p.py	Mon May 15 14:31:16 2006
@@ -115,6 +115,8 @@
     return lltype.direct_arrayitems(s.chars)
 
 def ll_charp2str(p):
+    if not p:
+        return lltype.nullptr(string_repr.lowleveltype.TO)
     length = ll_strlen(p)
     newstr = lltype.malloc(string_repr.lowleveltype.TO, length)
     for i in range(length):

Modified: pypy/dist/pypy/rpython/rctypes/test/test_rchar_p.py
==============================================================================
--- pypy/dist/pypy/rpython/rctypes/test/test_rchar_p.py	(original)
+++ pypy/dist/pypy/rpython/rctypes/test/test_rchar_p.py	Mon May 15 14:31:16 2006
@@ -112,6 +112,11 @@
             assert not c_char_p(None)
         interpret(func, [])
 
+    def test_null_ptr(self):
+        def func():
+            return pointer(c_char_p(None))[0] is None
+        assert interpret(func, [])
+        
     def test_convert_pointers(self):
         from pypy.rpython.rctypes.rchar_p import ll_strlen
         strlen = CFUNCTYPE(c_int, c_char_p)()   # not directly executable!
@@ -155,3 +160,10 @@
         fn = compile(func, [])
         res = fn()
         assert res == "hello"
+
+    def test_null_ptr(self):
+        def func():
+            return pointer(c_char_p(None))[0] is None
+        fn = compile(func, [])
+        assert fn()
+        


From antocuni at codespeak.net  Mon May 15 15:29:28 2006
From: antocuni at codespeak.net (antocuni at codespeak.net)
Date: Mon, 15 May 2006 15:29:28 +0200 (CEST)
Subject: [pypy-svn] r27237 - in pypy/dist/pypy/rpython: . lltypesystem
	ootypesystem test
Message-ID: <20060515132928.83E3E1009A@code0.codespeak.net>

Author: antocuni
Date: Mon May 15 15:29:19 2006
New Revision: 27237

Modified:
   pypy/dist/pypy/rpython/lltypesystem/rstr.py
   pypy/dist/pypy/rpython/ootypesystem/rstr.py
   pypy/dist/pypy/rpython/rstr.py
   pypy/dist/pypy/rpython/test/test_rstr.py
Log:
Add support for method join to ootypesystem rstr.



Modified: pypy/dist/pypy/rpython/lltypesystem/rstr.py
==============================================================================
--- pypy/dist/pypy/rpython/lltypesystem/rstr.py	(original)
+++ pypy/dist/pypy/rpython/lltypesystem/rstr.py	Mon May 15 15:29:19 2006
@@ -63,6 +63,13 @@
                             # where NULL is always valid: it is chr(0)
 
 
+    def _list_length_items(self, hop, v_lst, LIST):
+        LIST = LIST.TO
+        v_length = hop.gendirectcall(LIST.ll_length, v_lst)
+        v_items = hop.gendirectcall(LIST.ll_items, v_lst)
+        return v_length, v_items
+
+
 class CharRepr(AbstractCharRepr, StringRepr):
     lowleveltype = Char
 

Modified: pypy/dist/pypy/rpython/ootypesystem/rstr.py
==============================================================================
--- pypy/dist/pypy/rpython/ootypesystem/rstr.py	(original)
+++ pypy/dist/pypy/rpython/ootypesystem/rstr.py	Mon May 15 15:29:19 2006
@@ -43,6 +43,14 @@
     def make_iterator_repr(self):
         return string_iterator_repr
 
+    def _list_length_items(self, hop, v_lst, LIST):
+        # ootypesystem list has a different interface that
+        # lltypesystem list, so we don't need to calculate the lenght
+        # here and to pass the 'items' array. Let's pass the list
+        # itself and let LLHelpers.join to manipulate it directly.
+        c_length = hop.inputconst(ootype.Void, None)
+        return c_length, v_lst
+
 
 class CharRepr(AbstractCharRepr, StringRepr):
     lowleveltype = Char
@@ -56,13 +64,13 @@
         return ootype.oostring(ch)
 
     def ll_char_mul(ch, times):
-        builder = ootype.new(ootype.StringBuilder)
-        builder.ll_allocate(times)
+        buf = ootype.new(ootype.StringBuilder)
+        buf.ll_allocate(times)
         i = 0
         while i 0:
+            lastitem = lst.ll_getitem_fast(i)
+            buf.ll_append(lastitem)
+        return buf.ll_build()
+
+    def ll_join_chars(length_dummy, lst):
+        buf = ootype.new(ootype.StringBuilder)
+        length = lst.ll_length()
+        buf.ll_allocate(length)
+        i = 0
+        while i < length:
+            buf.ll_append_char(lst.ll_getitem_fast(i))
+            i += 1
+        return buf.ll_build()
+
+    def ll_join_strs(length_dummy, lst):
+        buf = ootype.new(ootype.StringBuilder)
+        length = lst.ll_length()
+        #buf.ll_allocate(length)
+        i = 0
+        while i < length:
+            buf.ll_append(lst.ll_getitem_fast(i))
+            i += 1
+        return buf.ll_build()
+
+
 def add_helpers():
     dic = {}
     for name, meth in ootype.String._GENERIC_METHODS.iteritems():
@@ -99,6 +153,7 @@
 unichar_repr = UniCharRepr()
 char_repr.ll = LLHelpers
 unichar_repr.ll = LLHelpers
+emptystr = string_repr.convert_const("")
 
 class StringIteratorRepr(AbstractStringIteratorRepr):
     lowleveltype = ootype.Record({'string': string_repr.lowleveltype,

Modified: pypy/dist/pypy/rpython/rstr.py
==============================================================================
--- pypy/dist/pypy/rpython/rstr.py	(original)
+++ pypy/dist/pypy/rpython/rstr.py	Mon May 15 15:29:19 2006
@@ -135,7 +135,12 @@
         v_str, = hop.inputargs(string_repr)
         hop.exception_cannot_occur()
         return hop.gendirectcall(self.ll.ll_lower, v_str)
-        
+
+    def _list_length_items(self, hop, v_lst, LIST):
+        """Return two Variables containing the length and items of a
+        list. Need to be overriden because it is typesystem-specific."""
+        raise NotImplementedError
+
     def rtype_method_join(self, hop):
         hop.exception_cannot_occur()
         rstr = hop.rtyper.type_system.rstr
@@ -145,10 +150,8 @@
         if not isinstance(r_lst, hop.rtyper.type_system.rlist.BaseListRepr):
             raise TyperError("string.join of non-list: %r" % r_lst)
         v_str, v_lst = hop.inputargs(rstr.string_repr, r_lst)
-        LIST = r_lst.lowleveltype.TO
-        v_length = hop.gendirectcall(LIST.ll_length, v_lst)
-        v_items = hop.gendirectcall(LIST.ll_items, v_lst)
-                       
+        v_length, v_items = self._list_length_items(hop, v_lst, r_lst.lowleveltype)
+
         if hop.args_s[0].is_constant() and hop.args_s[0].const == '':
             if r_lst.item_repr == rstr.string_repr:
                 llfn = self.ll.ll_join_strs

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	Mon May 15 15:29:19 2006
@@ -325,37 +325,37 @@
             res = self.interpret(fn, [i])
             assert self.ll_to_string(res) == fn(i)
 
-def test_join():
-    res = interpret(lambda: ''.join([]), [])
-    assert ''.join(res.chars) == ""
-
-    res = interpret(lambda: ''.join(['a', 'b', 'c']), [])
-    assert ''.join(res.chars) == "abc"
-
-    res = interpret(lambda: ''.join(['abc', 'de', 'fghi']), [])
-    assert ''.join(res.chars) == "abcdefghi"
-
-    res = interpret(lambda: '.'.join(['abc', 'def']), [])
-    assert ''.join(res.chars) == 'abc.def'
-    
-    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)
-
-    def fn(i, j):
-        s1 = [ '', ',', ' and ']
-        s2 = [ [], ['foo'], ['bar', 'baz', 'bazz']]
-        s2[1].extend(['x'])
-        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)
+    def test_join(self):
+        res = self.interpret(lambda: ''.join([]), [])
+        assert self.ll_to_string(res) == ""
+
+        res = self.interpret(lambda: ''.join(['a', 'b', 'c']), [])
+        assert self.ll_to_string(res) == "abc"
+
+        res = self.interpret(lambda: ''.join(['abc', 'de', 'fghi']), [])
+        assert self.ll_to_string(res) == "abcdefghi"
+
+        res = self.interpret(lambda: '.'.join(['abc', 'def']), [])
+        assert self.ll_to_string(res) == 'abc.def'
+
+        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 = self.interpret(fn, [i,j])
+                assert self.ll_to_string(res) == fn(i, j)
+
+        def fn(i, j):
+            s1 = [ '', ',', ' and ']
+            s2 = [ [], ['foo'], ['bar', 'baz', 'bazz']]
+            s2[1].extend(['x'])
+            return s1[i].join(s2[j])
+        for i in range(3):
+            for j in range(3):
+                res = self.interpret(fn, [i,j])
+                assert self.ll_to_string(res) == fn(i, j)
 
 def test_parse_fmt():
     assert LLHelpers.parse_fmt_string('a') == ['a']


From antocuni at codespeak.net  Mon May 15 15:44:37 2006
From: antocuni at codespeak.net (antocuni at codespeak.net)
Date: Mon, 15 May 2006 15:44:37 +0200 (CEST)
Subject: [pypy-svn] r27238 - in pypy/dist/pypy/rpython: ootypesystem test
Message-ID: <20060515134437.684111009A@code0.codespeak.net>

Author: antocuni
Date: Mon May 15 15:44:29 2006
New Revision: 27238

Modified:
   pypy/dist/pypy/rpython/ootypesystem/ootype.py
   pypy/dist/pypy/rpython/ootypesystem/rstr.py
   pypy/dist/pypy/rpython/test/test_rstr.py
Log:
Added support for slices to ootypesystem rstr.



Modified: pypy/dist/pypy/rpython/ootypesystem/ootype.py
==============================================================================
--- pypy/dist/pypy/rpython/ootypesystem/ootype.py	(original)
+++ pypy/dist/pypy/rpython/ootypesystem/ootype.py	Mon May 15 15:44:29 2006
@@ -289,6 +289,7 @@
             "ll_strip": Meth([Char, Bool, Bool], self.SELFTYPE_T),
             "ll_upper": Meth([], self.SELFTYPE_T),
             "ll_lower": Meth([], self.SELFTYPE_T),
+            "ll_substring": Meth([Signed, Signed], self.SELFTYPE_T), # ll_substring(start, count)
             })
         self._setup_methods(generic_types)
 
@@ -867,6 +868,9 @@
         # NOT_RPYTHON
         return make_string(self._str.lower())
 
+    def ll_substring(self, start, count):
+        # NOT_RPYTHON
+        return make_string(self._str[start:start+count])
 
 class _null_string(_null_mixin(_string), _string):
     def __init__(self, STRING):

Modified: pypy/dist/pypy/rpython/ootypesystem/rstr.py
==============================================================================
--- pypy/dist/pypy/rpython/ootypesystem/rstr.py	(original)
+++ pypy/dist/pypy/rpython/ootypesystem/rstr.py	Mon May 15 15:44:29 2006
@@ -129,6 +129,19 @@
             i += 1
         return buf.ll_build()
 
+    def ll_stringslice_startonly(s, start):
+        return s.ll_substring(start, s.ll_strlen() - start)
+
+    def ll_stringslice(s, slice):
+        start = slice.start
+        stop = slice.stop
+        length = s.ll_strlen()        
+        if stop > length:
+            stop = length
+        return s.ll_substring(start, stop-start)
+
+    def ll_stringslice_minusone(s):
+        return s.ll_substring(0, s.ll_strlen()-1)
 
 def add_helpers():
     dic = {}

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	Mon May 15 15:44:29 2006
@@ -357,6 +357,25 @@
                 res = self.interpret(fn, [i,j])
                 assert self.ll_to_string(res) == fn(i, j)
 
+    def test_str_slice(self):
+        def fn():
+            s = 'hello'
+            s1 = s[:3]
+            s2 = s[3:]
+            s3 = s[3:10]
+            return s1+s2 == s and s2+s1 == 'lohel' and s1+s3 == s
+        res = self.interpret(fn, ())
+        assert res
+
+    def test_str_slice_minusone(self):
+        def fn():
+            s = 'hello'
+            z = 'h'
+            return s[:-1]+z[:-1]
+        res = self.interpret(fn, ())
+        assert self.ll_to_string(res) == 'hell'
+
+
 def test_parse_fmt():
     assert LLHelpers.parse_fmt_string('a') == ['a']
     assert LLHelpers.parse_fmt_string('%s') == [('s',)]
@@ -413,25 +432,6 @@
     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:]
-        s3 = s[3:10]
-        return s1+s2 == s and s2+s1 == 'lohel' and s1+s3 == s
-    res = interpret(fn, ())
-    assert res
-
-def test_str_slice_minusone():
-    def fn():
-        s = 'hello'
-        z = 'h'
-        return s[:-1]+z[:-1]
-    res = interpret(fn, ())
-    assert ''.join(res.chars) == 'hell'
-
-
 def test_strformat_instance():
     class C:
         pass


From pedronis at codespeak.net  Mon May 15 15:45:42 2006
From: pedronis at codespeak.net (pedronis at codespeak.net)
Date: Mon, 15 May 2006 15:45:42 +0200 (CEST)
Subject: [pypy-svn] r27239 - pypy/dist/pypy/rpython/memory/test
Message-ID: <20060515134542.8227D1009A@code0.codespeak.net>

Author: pedronis
Date: Mon May 15 15:45:41 2006
New Revision: 27239

Modified:
   pypy/dist/pypy/rpython/memory/test/test_support.py
Log:
don't use the simulator for the one llinterped support test. 



Modified: pypy/dist/pypy/rpython/memory/test/test_support.py
==============================================================================
--- pypy/dist/pypy/rpython/memory/test/test_support.py	(original)
+++ pypy/dist/pypy/rpython/memory/test/test_support.py	Mon May 15 15:45:41 2006
@@ -1,12 +1,12 @@
 from pypy.rpython.objectmodel import free_non_gc_object
 from pypy.rpython.memory.support import get_address_linked_list
-from pypy.rpython.memory import support
-from pypy.rpython.memory.lladdress import raw_malloc, raw_free, NULL
-from pypy.rpython.memory.test.test_llinterpsim import interpret
 
+from pypy.rpython.test.test_llinterp import interpret
+from pypy.rpython.lltypesystem import lltype, llmemory
 
 class TestAddressLinkedList(object):
     def test_simple_access(self):
+        from pypy.rpython.memory.lladdress import raw_malloc, raw_free, NULL
         AddressLinkedList = get_address_linked_list()
         addr = raw_malloc(100)
         ll = AddressLinkedList()
@@ -33,6 +33,7 @@
         raw_free(addr)
 
     def test_big_access(self):
+        from pypy.rpython.memory.lladdress import raw_malloc, raw_free, NULL        
         AddressLinkedList = get_address_linked_list()
         addr = raw_malloc(1)
         ll = AddressLinkedList()
@@ -53,47 +54,48 @@
         raw_free(addr)
         
 def test_linked_list_annotate():
-    AddressLinkedList = get_address_linked_list(10)
+    AddressLinkedList = get_address_linked_list(60)
+    INT_SIZE = llmemory.sizeof(lltype.Signed)
     def f():
-        addr = raw_malloc(100)
+        addr = raw_malloc(INT_SIZE*100)
         ll = AddressLinkedList()
         ll.append(addr)
-        ll.append(addr + 1)
-        ll.append(addr + 2)
+        ll.append(addr + INT_SIZE*1)
+        ll.append(addr + INT_SIZE*2)
         a = ll.pop()
-        res = (a - addr == 2)
+        res = (a - INT_SIZE*2 == addr)
         a = ll.pop()
-        res = res and (a - addr == 1)
+        res = res and (a - INT_SIZE*1 == addr)
         a = ll.pop()
         res = res and a == addr
         res = res and (ll.pop() == NULL)
         res = res and (ll.pop() == NULL)
         ll.append(addr)
-        for i in range(30):
-            ll.append(addr + i)
-        for i in range(29, -1, -1):
+        for i in range(300):
+            ll.append(addr + INT_SIZE*i)
+        for i in range(299, -1, -1):
             a = ll.pop()
-            res = res and (a - addr == i)
-        for i in range(30):
-            ll.append(addr + i)
-        for i in range(29, -1, -1):
+            res = res and (a - INT_SIZE*i == addr)
+        for i in range(300):
+            ll.append(addr + INT_SIZE*i)
+        for i in range(299, -1, -1):
             a = ll.pop()
-            res = res and (a - addr == i)
+            res = res and (a - INT_SIZE*i == addr)
         ll.free()
         free_non_gc_object(ll)
         ll = AddressLinkedList()
         ll.append(addr)
-        ll.append(addr + 1)
-        ll.append(addr + 2)
+        ll.append(addr + INT_SIZE*1)
+        ll.append(addr + INT_SIZE*2)
         ll.free()
         free_non_gc_object(ll)
         raw_free(addr)
         return res
-##     a = RPythonAnnotator()
-##     res = a.build_types(f, [])
-##     a.translator.specialize()
-##     a.translator.view()
+
+    NULL = llmemory.NULL
+    raw_malloc, raw_free = llmemory.raw_malloc, llmemory.raw_free
     assert f()
+    from pypy.rpython.memory.lladdress import raw_malloc, raw_free
     AddressLinkedList = get_address_linked_list()
     res = interpret(f, [])
     assert res


From ac at codespeak.net  Mon May 15 17:46:56 2006
From: ac at codespeak.net (ac at codespeak.net)
Date: Mon, 15 May 2006 17:46:56 +0200 (CEST)
Subject: [pypy-svn] r27240 - pypy/dist/pypy/module/_socket
Message-ID: <20060515154656.70ADF1009A@code0.codespeak.net>

Author: ac
Date: Mon May 15 17:46:55 2006
New Revision: 27240

Modified:
   pypy/dist/pypy/module/_socket/interp_socket.py
Log:
Release the GIL in (some) blocking methods.
Fix bugs in recvfrom and w_makesockaddr.
Several tests in CPythons test_socket.py now pass :-)



Modified: pypy/dist/pypy/module/_socket/interp_socket.py
==============================================================================
--- pypy/dist/pypy/module/_socket/interp_socket.py	(original)
+++ pypy/dist/pypy/module/_socket/interp_socket.py	Mon May 15 17:46:55 2006
@@ -135,6 +135,10 @@
     return addr
 		
 def w_makesockaddr(space, caddr, caddrlen, proto):
+    if caddrlen == 0:
+        # No address -- may be recvfrom() from known socket
+        return space.w_None
+
     if caddr.contents.sa_family == _c.AF_INET:
         a = _c.cast(caddr, ctypes.POINTER(_c.sockaddr_in))
         return space.newtuple([space.wrap(_c.inet_ntoa(a.contents.sin_addr)),
@@ -826,8 +830,14 @@
         """
         peeraddr = _c.pointer(_c.sockaddr())
         peeraddrlen = _c.socklen_t(_c.sockaddr_size)
+
+        # XXX Temporary hack for releasing the GIL
+        GIL = space.threadlocals.getGIL()
+        if GIL is not None: GIL.release()
         newfd = _c.socketaccept(self.fd, peeraddr,
                                 _c.pointer(peeraddrlen))
+        if GIL is not None: GIL.acquire(True)
+        
         if newfd < 0:
             raise w_get_socketerror(space, None, _c.geterrno())
         newsocket = Socket(space, newfd, self.family, self.type, self.proto)
@@ -847,6 +857,10 @@
             raise w_get_socketerror(space, None, _c.geterrno())
     bind.unwrap_spec = ['self', ObjSpace, W_Root]
 
+    def __del__(self):
+        if not self.closed:
+            _c.close(self.fd)
+
     def close(self, space):
         """close()
 
@@ -878,7 +892,13 @@
         instead of raising an exception when an error occurs.
         """
         sockaddr_ptr, sockaddr_len = self._getsockaddr(space, w_addr)
+
+        # XXX Temporary hack for releasing the GIL
+        GIL = space.threadlocals.getGIL()
+        if GIL is not None: GIL.release()
         err = _c.socketconnect(self.fd, sockaddr_ptr, sockaddr_len)
+        if GIL is not None: GIL.acquire(True)
+
         if err:
             errno = _c.geterrno()
             if self.timeout > 0.0:
@@ -998,7 +1018,13 @@
         the remote end is closed and all data is read, return the empty string.
         """
         buf = _c.create_string_buffer(buffersize)
+
+        # XXX Temporary hack for releasing the GIL
+        GIL = space.threadlocals.getGIL()
+        if GIL is not None: GIL.release()
         read_bytes = _c.socketrecv(self.fd, buf, buffersize, flags)
+        if GIL is not None: GIL.acquire(True)
+
         if read_bytes < 0:
             raise w_get_socketerror(space, None, _c.geterrno())
         return space.wrap(buf[:read_bytes])
@@ -1012,12 +1038,18 @@
         """
         buf = _c.create_string_buffer(buffersize)
         sockaddr = _c.sockaddr()
-        sockaddr_size = _c.socklen_t()
+        sockaddr_size = _c.socklen_t(_c.sockaddr_size)
+
+        # XXX Temporary hack for releasing the GIL
+        GIL = space.threadlocals.getGIL()
+        if GIL is not None: GIL.release()
         read_bytes = _c.recvfrom(self.fd, buf, buffersize, flags,
                                  _c.pointer(sockaddr), _c.pointer(sockaddr_size))
-        w_addr = w_makesockaddr(space, _c.pointer(sockaddr), sockaddr_size.value, self.proto)
+        if GIL is not None: GIL.acquire(True)
+
         if read_bytes < 0:
             raise w_get_socketerror(space, None, _c.geterrno())
+        w_addr = w_makesockaddr(space, _c.pointer(sockaddr), sockaddr_size.value, self.proto)
         return space.newtuple([space.wrap(buf[:read_bytes]), w_addr])
     recvfrom.unwrap_spec = ['self', ObjSpace, int, int]
 
@@ -1028,7 +1060,13 @@
         argument, see the Unix manual.  Return the number of bytes
         sent; this may be less than len(data) if the network is busy.
         """
+
+        # XXX Temporary hack for releasing the GIL
+        GIL = space.threadlocals.getGIL()
+        if GIL is not None: GIL.release()
         res = _c.send(self.fd, data, len(data), flags)
+        if GIL is not None: GIL.acquire(True)
+
         if res < 0:
             raise w_get_socketerror(space, None, _c.geterrno())
         return space.wrap(res)
@@ -1043,7 +1081,13 @@
         to tell how much data has been sent.
         """
         while data:
+
+            # XXX Temporary hack for releasing the GIL
+            GIL = space.threadlocals.getGIL()
+            if GIL is not None: GIL.release()
             res = _c.send(self.fd, data, len(data), flags)
+            if GIL is not None: GIL.acquire(True)
+
             if res < 0:
                 raise w_get_socketerror(space, None, _c.geterrno())
             data = data[res:]
@@ -1063,7 +1107,13 @@
             # 3 args version
             flags = space.int_w(w_param2)
             addr, addr_len = self._getsockaddr(space, w_param3)
+
+        # XXX Temporary hack for releasing the GIL
+        GIL = space.threadlocals.getGIL()
+        if GIL is not None: GIL.release()
         res = _c.sendto(self.fd, data, len(data), flags, addr, addr_len)
+        if GIL is not None: GIL.acquire(True)
+
         if res < 0:
             raise w_get_socketerror(space, None, _c.geterrno())
         return space.wrap(res)
@@ -1142,6 +1192,8 @@
         
     shutdown.unwrap_spec = ['self', ObjSpace, int]
 
+
+
 app_makefile = gateway.applevel(r'''
 def makefile(self, mode="r", buffersize=-1):
     """makefile([mode[, buffersize]]) -> file object


From pedronis at codespeak.net  Mon May 15 17:48:32 2006
From: pedronis at codespeak.net (pedronis at codespeak.net)
Date: Mon, 15 May 2006 17:48:32 +0200 (CEST)
Subject: [pypy-svn] r27241 - in pypy/dist/pypy/rpython/memory: . test
Message-ID: <20060515154832.96832100A4@code0.codespeak.net>

Author: pedronis
Date: Mon May 15 17:48:30 2006
New Revision: 27241

Added:
   pypy/dist/pypy/rpython/memory/test/test_transformed_gc.py
      - copied, changed from r27234, pypy/dist/pypy/rpython/memory/test/test_gc.py
Modified:
   pypy/dist/pypy/rpython/memory/gc.py
   pypy/dist/pypy/rpython/memory/gctransform.py
   pypy/dist/pypy/rpython/memory/lltypelayout.py
Log:
start of refactoring to allow gcs to be tested through the transformer on top of llinterp. Collection
still is crashing because of misconstructed fakeaddresses.

half-way to making it easier to swap in gcs when using the Framework policy and transformer.

fix in lltypelayout.sizeof

added statics functionality support at least in mark-and-sweep gc.



Modified: pypy/dist/pypy/rpython/memory/gc.py
==============================================================================
--- pypy/dist/pypy/rpython/memory/gc.py	(original)
+++ pypy/dist/pypy/rpython/memory/gc.py	Mon May 15 17:48:30 2006
@@ -245,6 +245,11 @@
         # the strings!  so it must be at the end
         os.write(2, "freed %s bytes. the heap is now %s bytes.\n" % (freed_size, curr_heap_size))
 
+    STATISTICS_NUMBERS = 2
+
+    def statistics(self):
+        return self.heap_size, self.bytes_malloced
+
     def size_gc_header(self, typeid=0):
         return MarkSweepGC._size_gc_header
 

Modified: pypy/dist/pypy/rpython/memory/gctransform.py
==============================================================================
--- pypy/dist/pypy/rpython/memory/gctransform.py	(original)
+++ pypy/dist/pypy/rpython/memory/gctransform.py	Mon May 15 17:48:30 2006
@@ -731,14 +731,16 @@
     use_stackless = False
     extra_static_slots = 0
 
+    from pypy.rpython.memory.gc import MarkSweepGC as GCClass
+    GC_PARAMS = {'start_heap_size': 8*1024*1024 # XXX adjust
+                 }
+    
     def __init__(self, translator):
         from pypy.rpython.memory.support import get_address_linked_list
         super(FrameworkGCTransformer, self).__init__(translator, inline=True)
         AddressLinkedList = get_address_linked_list()
+        GCClass = self.GCClass
         class GCData(object):
-            from pypy.rpython.memory.gc import MarkSweepGC as GCClass
-            startheapsize = 8*1024*1024 # XXX adjust
-
             # types of the GC information tables
             OFFSETS_TO_GC_PTR = lltype.Array(lltype.Signed)
             TYPE_INFO = lltype.Struct("type_info",
@@ -796,7 +798,7 @@
         sizeofaddr = llmemory.sizeof(llmemory.Address)
 
         StackRootIterator = self.build_stack_root_iterator()
-        gcdata.gc = GCData.GCClass(AddressLinkedList, GCData.startheapsize, StackRootIterator)
+        gcdata.gc = GCClass(AddressLinkedList, get_roots=StackRootIterator, **self.GC_PARAMS)
 
         def frameworkgc_setup():
             # run-time initialization code
@@ -854,26 +856,31 @@
                                       annmodel.s_None,
                                       inline = True)
 
-        classdef = bk.getuniqueclassdef(GCData.GCClass)
+        classdef = bk.getuniqueclassdef(GCClass)
         s_gcdata = annmodel.SomeInstance(classdef)
         self.malloc_fixedsize_ptr = getfn(
-            GCData.GCClass.malloc_fixedsize.im_func,
+            GCClass.malloc_fixedsize.im_func,
             [s_gcdata, annmodel.SomeInteger(nonneg=True),
              annmodel.SomeInteger(nonneg=True),
              annmodel.SomeBool()], annmodel.SomeAddress(),
             inline = True)
         self.malloc_varsize_ptr = getfn(
-            GCData.GCClass.malloc_varsize.im_func,
+            GCClass.malloc_varsize.im_func,
             [s_gcdata] + [annmodel.SomeInteger(nonneg=True) for i in range(5)]
             + [annmodel.SomeBool()], annmodel.SomeAddress())
-        self.collect_ptr = getfn(GCData.GCClass.collect.im_func,
+        self.collect_ptr = getfn(GCClass.collect.im_func,
             [s_gcdata], annmodel.s_None)
+
+        statics_s = (annmodel.SomeInteger(),)*GCClass.STATISTICS_NUMBERS
+        self.statistics_ptr = getfn(GCClass.statistics.im_func,
+                                    [s_gcdata], annmodel.SomeTuple(statics_s))
+                                   
         annhelper.finish()   # at this point, annotate all mix-level helpers
 
         self.collect_analyzer = CollectAnalyzer(self.translator)
         self.collect_analyzer.analyze_all()
 
-        s_gc = self.translator.annotator.bookkeeper.valueoftype(self.gcdata.GCClass)
+        s_gc = self.translator.annotator.bookkeeper.valueoftype(GCClass)
         r_gc = self.translator.rtyper.getrepr(s_gc)
         self.c_const_gc = rmodel.inputconst(r_gc, self.gcdata.gc)
 

Modified: pypy/dist/pypy/rpython/memory/lltypelayout.py
==============================================================================
--- pypy/dist/pypy/rpython/memory/lltypelayout.py	(original)
+++ pypy/dist/pypy/rpython/memory/lltypelayout.py	Mon May 15 17:48:30 2006
@@ -75,6 +75,8 @@
         return 0
     elif isinstance(TYPE, lltype.PyObjectType):
         return 0
+    elif isinstance(TYPE, lltype.Ptr):
+        return 0
     else:
         assert 0, "not yet implemented"
 


From pedronis at codespeak.net  Mon May 15 18:30:02 2006
From: pedronis at codespeak.net (pedronis at codespeak.net)
Date: Mon, 15 May 2006 18:30:02 +0200 (CEST)
Subject: [pypy-svn] r27245 - in pypy/dist/pypy: rpython/memory translator/c
Message-ID: <20060515163002.90B4F10093@code0.codespeak.net>

Author: pedronis
Date: Mon May 15 18:30:00 2006
New Revision: 27245

Modified:
   pypy/dist/pypy/rpython/memory/gctransform.py
   pypy/dist/pypy/translator/c/gc.py
Log:
generalize they way genc obtains gc header type info and values for constants for the framework case.



Modified: pypy/dist/pypy/rpython/memory/gctransform.py
==============================================================================
--- pypy/dist/pypy/rpython/memory/gctransform.py	(original)
+++ pypy/dist/pypy/rpython/memory/gctransform.py	Mon May 15 18:30:00 2006
@@ -884,6 +884,13 @@
         r_gc = self.translator.rtyper.getrepr(s_gc)
         self.c_const_gc = rmodel.inputconst(r_gc, self.gcdata.gc)
 
+        gc_header_offset = self.gcdata.gc.size_gc_header()
+        HDR = self._gc_HDR = gc_header_offset.minimal_layout
+        self._gc_fields = fields = []
+        for fldname in HDR._names:
+            FLDTYPE = getattr(HDR, fldname)
+            fields.append((fldname, FLDTYPE))
+
     def build_stack_root_iterator(self):
         gcdata = self.gcdata
         sizeofaddr = llmemory.sizeof(llmemory.Address)
@@ -987,6 +994,17 @@
                 for a in gc_pointers_inside(value, llmemory.fakeaddress(value)):
                     self.addresses_of_static_ptrs_in_nongc.append(a)
 
+    def gc_fields(self):
+        return self._gc_fields
+
+    def gc_field_values_for(self, obj):
+        HDR = self._gc_HDR
+        p_hdr = lltype.malloc(HDR, immortal=True)
+        hdr_adr = llmemory.cast_ptr_to_adr(p_hdr)
+        vals = []
+        self.gcdata.gc.init_gc_object(hdr_adr, self.get_type_id(lltype.typeOf(obj)))
+        return [getattr(p_hdr, fldname) for fldname in HDR._names]
+
     def offsets2table(self, offsets, TYPE):
         try:
             return self.offsettable_cache[TYPE]

Modified: pypy/dist/pypy/translator/c/gc.py
==============================================================================
--- pypy/dist/pypy/translator/c/gc.py	(original)
+++ pypy/dist/pypy/translator/c/gc.py	Mon May 15 18:30:00 2006
@@ -374,18 +374,16 @@
         # %s = %s; /* for moving GCs */' % (args[1], args[0])
 
     def common_gcheader_definition(self, defnode):
-        # XXX assumes mark and sweep
-        return [('typeid', lltype.Signed)]
+        return defnode.db.gctransformer.gc_fields()
 
     def common_gcheader_initdata(self, defnode):
-        # XXX this more or less assumes mark-and-sweep gc
         o = defnode.obj
         while True:
             n = o._parentstructure()
             if n is None:
                 break
             o = n
-        return [defnode.db.gctransformer.id_of_type[typeOf(o)] << 1]
+        return defnode.db.gctransformer.gc_field_values_for(o)
 
     def zero_malloc(self, TYPE, esize, eresult):
         assert TYPE._gcstatus()   # we don't really support this


From arigo at codespeak.net  Mon May 15 19:33:13 2006
From: arigo at codespeak.net (arigo at codespeak.net)
Date: Mon, 15 May 2006 19:33:13 +0200 (CEST)
Subject: [pypy-svn] r27248 - in pypy/dist/pypy: interpreter
	interpreter/pyparser lib objspace objspace/flow objspace/std
	objspace/std/test rpython/lltypesystem
	rpython/ootypesystem/test rpython/test tool tool/algo
	translator/backendopt translator/c translator/c/test
Message-ID: <20060515173313.842A110093@code0.codespeak.net>

Author: arigo
Date: Mon May 15 19:33:06 2006
New Revision: 27248

Modified:
   pypy/dist/pypy/interpreter/baseobjspace.py
   pypy/dist/pypy/interpreter/nestedscope.py
   pypy/dist/pypy/interpreter/pyparser/syntaxtree.py
   pypy/dist/pypy/lib/_classobj.py
   pypy/dist/pypy/objspace/flow/framestate.py
   pypy/dist/pypy/objspace/logic.py
   pypy/dist/pypy/objspace/std/default.py
   pypy/dist/pypy/objspace/std/test/test_obj.py
   pypy/dist/pypy/rpython/lltypesystem/rclass.py
   pypy/dist/pypy/rpython/ootypesystem/test/test_ooclean.py
   pypy/dist/pypy/rpython/test/test_rclass.py
   pypy/dist/pypy/tool/algo/unionref.py
   pypy/dist/pypy/tool/uid.py
   pypy/dist/pypy/translator/backendopt/escape.py
   pypy/dist/pypy/translator/c/exceptiontransform.py
   pypy/dist/pypy/translator/c/test/test_typed.py
Log:
Trying to generally fix id() issues.


Modified: pypy/dist/pypy/interpreter/baseobjspace.py
==============================================================================
--- pypy/dist/pypy/interpreter/baseobjspace.py	(original)
+++ pypy/dist/pypy/interpreter/baseobjspace.py	Mon May 15 19:33:06 2006
@@ -3,8 +3,8 @@
 from pypy.interpreter.argument import Arguments, ArgumentsFromValuestack
 from pypy.interpreter.pycompiler import CPythonCompiler, PythonAstCompiler
 from pypy.interpreter.miscutils import ThreadLocals
-from pypy.tool.cache import Cache 
-from pypy.rpython.rarithmetic import r_uint
+from pypy.tool.cache import Cache
+from pypy.tool.uid import HUGEVAL_BYTES
 import os
 
 __all__ = ['ObjSpace', 'OperationError', 'Wrappable', 'W_Root']
@@ -48,9 +48,23 @@
             raise
 
     def getrepr(self, space, info):
-        id = space.int_w(space.id(self)) # xxx ids could be long
-        id = r_uint(id) # XXX what about sizeof(void*) > sizeof(long) !!
-        return space.wrap("<%s at 0x%x>" % (info, id))
+        # XXX slowish
+        w_id = space.id(self)
+        w_4 = space.wrap(4)
+        w_0x0F = space.wrap(0x0F)
+        i = 2 * HUGEVAL_BYTES
+        addrstring = [' '] * i
+        while True:
+            n = space.int_w(space.and_(w_id, w_0x0F))
+            n += ord('0')
+            if n > ord('9'):
+                n += (ord('a') - ord('9') - 1)
+            i -= 1
+            addrstring[i] = chr(n)
+            if i == 0:
+                break
+            w_id = space.rshift(w_id, w_4)
+        return space.wrap("<%s at 0x%s>" % (info, ''.join(addrstring)))
 
     def getslotvalue(self, index):
         raise NotImplementedError

Modified: pypy/dist/pypy/interpreter/nestedscope.py
==============================================================================
--- pypy/dist/pypy/interpreter/nestedscope.py	(original)
+++ pypy/dist/pypy/interpreter/nestedscope.py	Mon May 15 19:33:06 2006
@@ -3,6 +3,7 @@
 from pypy.interpreter import function, pycode, pyframe
 from pypy.interpreter.baseobjspace import Wrappable
 from pypy.interpreter.mixedmodule import MixedModule
+from pypy.tool.uid import uid
 
 class Cell(Wrappable):
     "A simple container for a wrapped value."
@@ -55,7 +56,7 @@
         else:
             content = repr(self.w_value)
         return "<%s(%s) at 0x%x>" % (self.__class__.__name__,
-                                     content, id(self))
+                                     content, uid(self))
 
 
 class PyNestedScopeFrame(PyInterpFrame):

Modified: pypy/dist/pypy/interpreter/pyparser/syntaxtree.py
==============================================================================
--- pypy/dist/pypy/interpreter/pyparser/syntaxtree.py	(original)
+++ pypy/dist/pypy/interpreter/pyparser/syntaxtree.py	Mon May 15 19:33:06 2006
@@ -5,7 +5,9 @@
 # except ImportError:
 # #    from pysymbol import sym_values
 #     from pytoken import tok_values
-    
+
+from pypy.tool.uid import uid
+
 class AbstractSyntaxVisitor(object):
     def visit_syntaxnode( self, node ):
         pass
@@ -45,7 +47,7 @@
         return "".join(treenodes)
 
     def __repr__(self):
-        return "" % (self.name, id(self))
+        return "" % (self.name, uid(self))
 
     def __str__(self):
         return "(%s)" % self.name

Modified: pypy/dist/pypy/lib/_classobj.py
==============================================================================
--- pypy/dist/pypy/lib/_classobj.py	(original)
+++ pypy/dist/pypy/lib/_classobj.py	Mon May 15 19:33:06 2006
@@ -336,7 +336,7 @@
                 raise TypeError("__hash__() should return an int")
             return ret
         else:
-            return id(self)
+            return object.__hash__(self)
 
     def __len__(self):
         ret = instance_getattr1(self,'__len__')()

Modified: pypy/dist/pypy/objspace/flow/framestate.py
==============================================================================
--- pypy/dist/pypy/objspace/flow/framestate.py	(original)
+++ pypy/dist/pypy/objspace/flow/framestate.py	Mon May 15 19:33:06 2006
@@ -2,6 +2,7 @@
 from pypy.interpreter.error import OperationError
 from pypy.rpython.objectmodel import instantiate
 from pypy.objspace.flow.model import *
+from pypy.tool.uid import uid
 
 class FrameState:
     # XXX this class depends on the internal state of PyFrame objects
@@ -140,7 +141,7 @@
 
 class SpecTag(object):
     def __repr__(self):
-        return 'SpecTag(%d)' % id(self)
+        return 'SpecTag(0x%x)' % uid(self)
     def _freeze_(self):
         return True
 

Modified: pypy/dist/pypy/objspace/logic.py
==============================================================================
--- pypy/dist/pypy/objspace/logic.py	(original)
+++ pypy/dist/pypy/objspace/logic.py	Mon May 15 19:33:06 2006
@@ -2,6 +2,7 @@
 from pypy.interpreter import gateway, baseobjspace, argument
 from pypy.interpreter.error import OperationError
 from pypy.rpython.objectmodel import we_are_translated
+from pypy.tool.uid import uid
 
 # wrapped types, mm stuff
 from pypy.objspace.std.listobject import W_ListObject, W_TupleObject
@@ -150,7 +151,7 @@
             return not (self == other)
 
         def __repr__(self):
-            return '' % id(self)
+            return '' % uid(self)
 
     def construct_coroutine():
         if we_are_translated():

Modified: pypy/dist/pypy/objspace/std/default.py
==============================================================================
--- pypy/dist/pypy/objspace/std/default.py	(original)
+++ pypy/dist/pypy/objspace/std/default.py	Mon May 15 19:33:06 2006
@@ -8,8 +8,7 @@
 
 def id__ANY(space, w_obj):
     #print 'id:', w_obj
-    from pypy.objspace.std.inttype import wrapint
-    return wrapint(id(w_obj))
+    return space.wrap(id(w_obj))
 
 # __init__ should succeed if called internally as a multimethod
 

Modified: pypy/dist/pypy/objspace/std/test/test_obj.py
==============================================================================
--- pypy/dist/pypy/objspace/std/test/test_obj.py	(original)
+++ pypy/dist/pypy/objspace/std/test/test_obj.py	Mon May 15 19:33:06 2006
@@ -2,8 +2,9 @@
 
 class AppTestObject: 
     def test_hash_builtin(self):
+        import sys
         o = object()
-        assert hash(o) == id(o) 
+        assert (hash(o) & sys.maxint) == (id(o) & sys.maxint)
 
     def test_hash_method(self):
         o = object()
@@ -18,8 +19,9 @@
         assert not hasattr(o, '__getnewargs__')
 
     def test_hash_subclass(self):
+        import sys
         class X(object):
             pass
         x = X()
-        assert hash(x) == id(x)
+        assert (hash(x) & sys.maxint) == (id(x) & sys.maxint)
         assert hash(x) == object.__hash__(x)

Modified: pypy/dist/pypy/rpython/lltypesystem/rclass.py
==============================================================================
--- pypy/dist/pypy/rpython/lltypesystem/rclass.py	(original)
+++ pypy/dist/pypy/rpython/lltypesystem/rclass.py	Mon May 15 19:33:06 2006
@@ -20,6 +20,7 @@
 from pypy.rpython.extregistry import ExtRegistryEntry
 from pypy.annotation import model as annmodel
 from pypy.rpython.objectmodel import UnboxedValue
+from pypy.rpython.rarithmetic import intmask
 
 #
 #  There is one "vtable" per user class, with the following structure:
@@ -807,7 +808,7 @@
         return 0    # for None
     cached = ins.hash_cache
     if cached == 0:
-       cached = ins.hash_cache = id(ins)
+       cached = ins.hash_cache = intmask(id(ins))
     return cached
 
 def ll_inst_type(obj):

Modified: pypy/dist/pypy/rpython/ootypesystem/test/test_ooclean.py
==============================================================================
--- pypy/dist/pypy/rpython/ootypesystem/test/test_ooclean.py	(original)
+++ pypy/dist/pypy/rpython/ootypesystem/test/test_ooclean.py	Mon May 15 19:33:06 2006
@@ -2,6 +2,7 @@
 from pypy.rpython.ootypesystem import ootype
 from pypy.rpython.test.test_llinterp import get_interpreter
 import py
+import sys
 
 
 def check_only_ootype(graph):
@@ -446,7 +447,8 @@
         #     one line to the next
         current_identityhash = id(d2)
         instance_hash = hash(d2)
-        return current_identityhash == instance_hash
+        return ((current_identityhash & sys.maxint) ==
+                (instance_hash & sys.maxint))
     res = interpret(f1, [])
     assert res is True
 

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 May 15 19:33:06 2006
@@ -1,4 +1,5 @@
 import py
+import sys
 from pypy.translator.translator import TranslationContext, graphof
 from pypy.rpython.lltypesystem.lltype import *
 from pypy.rpython.ootypesystem import ootype
@@ -356,7 +357,8 @@
         d = D()
         def f():
             d2 = D()
-            x = hash(d2) == id(d2) # xxx check for this CPython peculiarity for now
+            # xxx check for this CPython peculiarity for now:
+            x = (hash(d2) & sys.maxint) == (id(d2) & sys.maxint)
             return x, hash(c)+hash(d)
 
         res = interpret(f, [], type_system=self.ts)

Modified: pypy/dist/pypy/tool/algo/unionref.py
==============================================================================
--- pypy/dist/pypy/tool/algo/unionref.py	(original)
+++ pypy/dist/pypy/tool/algo/unionref.py	Mon May 15 19:33:06 2006
@@ -18,6 +18,7 @@
 """
 
 import UserDict
+from pypy.tool.uid import uid
 
 
 class UnionRef(object):
@@ -112,7 +113,7 @@
         return result
 
     def __repr__(self):
-        return "" % id(self)
+        return "" % uid(self)
 
     def __getitem__(self, key):
         return self._data[key]()

Modified: pypy/dist/pypy/tool/uid.py
==============================================================================
--- pypy/dist/pypy/tool/uid.py	(original)
+++ pypy/dist/pypy/tool/uid.py	Mon May 15 19:33:06 2006
@@ -1,23 +1,32 @@
-import struct
+import struct, sys
 
 # This is temporary hack to run PyPy on PyPy
 # until PyPy's struct module handle P format character.
 try:
-    HUGEVAL = 256 ** struct.calcsize('P')
+    HUGEVAL_BYTES = struct.calcsize('P')
 except struct.error:
-    HUGEVAL = 0
+    if sys.maxint <= 2147483647:
+        HUGEVAL_BYTES = 4
+    else:
+        HUGEVAL_BYTES = 8
+
+HUGEVAL = 256 ** HUGEVAL_BYTES
+
 
 def fixid(result):
     if result < 0:
         result += HUGEVAL
     return result
 
-def uid(obj):
-    """
-    Return the id of an object as an unsigned number so that its hex
-    representation makes sense
-    """
-    return fixid(id(obj))
+if sys.version_info < (2, 5):
+    def uid(obj):
+        """
+        Return the id of an object as an unsigned number so that its hex
+        representation makes sense
+        """
+        return fixid(id(obj))
+else:
+    uid = id    # guaranteed to be positive from CPython 2.5 onwards
 
 
 class Hashable(object):

Modified: pypy/dist/pypy/translator/backendopt/escape.py
==============================================================================
--- pypy/dist/pypy/translator/backendopt/escape.py	(original)
+++ pypy/dist/pypy/translator/backendopt/escape.py	Mon May 15 19:33:06 2006
@@ -4,6 +4,7 @@
 from pypy.translator.simplify import get_graph
 from pypy.rpython.rmodel import inputconst
 from pypy.translator.backendopt import support
+from pypy.tool.uid import uid
 
 class CreationPoint(object):
     def __init__(self, creation_method="?"):
@@ -16,8 +17,8 @@
             self.malloced = False
 
     def __repr__(self):
-        return ("CreationPoint(<%s>, %s, esc=%s, cha=%s)" %
-                (id(self), self.creation_method, self.escapes, self.changes))
+        return ("CreationPoint(<0x%x>, %s, esc=%s, cha=%s)" %
+                (uid(self), self.creation_method, self.escapes, self.changes))
 
 class VarState(object):
     def __init__(self, crep=None):

Modified: pypy/dist/pypy/translator/c/exceptiontransform.py
==============================================================================
--- pypy/dist/pypy/translator/c/exceptiontransform.py	(original)
+++ pypy/dist/pypy/translator/c/exceptiontransform.py	Mon May 15 19:33:06 2006
@@ -137,8 +137,8 @@
         from the current graph with a special value (False/-1/-1.0/null).
         Because of the added exitswitch we need an additional block.
         """
-        assert id(graph) not in self.seen_graphs
-        self.seen_graphs[id(graph)] = True
+        assert graph not in self.seen_graphs
+        self.seen_graphs[graph] = True
         join_blocks(graph)
         # collect the blocks before changing them
         for block in list(graph.iterblocks()):

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 May 15 19:33:06 2006
@@ -594,7 +594,8 @@
         d = D()
         def fn():
             d2 = D()
-            x = hash(d2) == id(d2) # xxx check for this CPython peculiarity for now
+            # xxx check for this CPython peculiarity for now:
+            x = (hash(d2) & sys.maxint) == (id(d2) & sys.maxint)
             return x, hash(c)+hash(d)
         
         f = self.getcompiled(fn)


From tismer at codespeak.net  Mon May 15 19:48:00 2006
From: tismer at codespeak.net (tismer at codespeak.net)
Date: Mon, 15 May 2006 19:48:00 +0200 (CEST)
Subject: [pypy-svn] r27249 - pypy/dist/pypy/doc/discussion
Message-ID: <20060515174800.98F6E10093@code0.codespeak.net>

Author: tismer
Date: Mon May 15 19:47:59 2006
New Revision: 27249

Modified:
   pypy/dist/pypy/doc/discussion/howtoimplementpickling.txt
Log:
trying to explain a bit more why we should not add direct pickling support to certain builtin objects

Modified: pypy/dist/pypy/doc/discussion/howtoimplementpickling.txt
==============================================================================
--- pypy/dist/pypy/doc/discussion/howtoimplementpickling.txt	(original)
+++ pypy/dist/pypy/doc/discussion/howtoimplementpickling.txt	Mon May 15 19:47:59 2006
@@ -66,14 +66,35 @@
 It should be simple and straightforward to redo these implementations.
 Nevertheless there is a complication. The most natural way to support
 pickling is providing a __getstate__/__setstate__ method pair.
-This is ok for extension types like coroutines/tasklets, but
-not allowed to use for existing types, since adding new methods
-would change the interface of these objects. For Stackless,
+This is ok for extension types like coroutines/tasklets which we can
+control, but it should be avoided for existing types.
+
+Consider for instance frames. We would have to add a __getstate__
+and a __setstate__ method, which is an interface change. Furthermore,
+we would need to support creation of frames by calling the
+frame type, which is not really intended.
+
+For other types with are already callable, things get more complicated
+because we need to make sure that creating new instances does
+not interfere with existing ways to call the type.
+
+Directly adding a pickling interface to existing types is quite
+likely to produce overlaps in the calling interface. This happened
+for instance, when the module type became callable, and the signature
+was different from what Stackless added before.
+
+For Stackless,
 I used the copyreg module, instead, and created special surrogate
 objects as placeholders, which replace the type of the object
 after unpickling with the right type pointer. For details, see
 the prickelpit.c file in the Stackless distribution.
 
+As a conclusion, pickling of tasklets is an addition to Stackless,
+but not meand to be an extension to Python. The need to support
+pickling of certain objects should not change the interface.
+It is better to decouple this and to use surrogate types for
+pickling which cannot collide with future additions to Python.
+
 The real problem
 ................
 


From pedronis at codespeak.net  Mon May 15 20:20:50 2006
From: pedronis at codespeak.net (pedronis at codespeak.net)
Date: Mon, 15 May 2006 20:20:50 +0200 (CEST)
Subject: [pypy-svn] r27250 - in pypy/dist/pypy/rpython: lltypesystem memory
	memory/test
Message-ID: <20060515182050.84AB11009A@code0.codespeak.net>

Author: pedronis
Date: Mon May 15 20:20:48 2006
New Revision: 27250

Modified:
   pypy/dist/pypy/rpython/lltypesystem/llmemory.py
   pypy/dist/pypy/rpython/memory/gc.py
   pypy/dist/pypy/rpython/memory/gctransform.py
   pypy/dist/pypy/rpython/memory/test/test_transformed_gc.py
Log:
some fixes. test_transformed_gc still crashes if we change the parameters to get a collection: it's trying
to add a rpy_string.chars offset to a ExcData structure (?)



Modified: pypy/dist/pypy/rpython/lltypesystem/llmemory.py
==============================================================================
--- pypy/dist/pypy/rpython/lltypesystem/llmemory.py	(original)
+++ pypy/dist/pypy/rpython/lltypesystem/llmemory.py	Mon May 15 20:20:48 2006
@@ -303,7 +303,9 @@
                 offset = other
             else:
                 offset = self.offset + other
-            return fakeaddress(self.ob, offset)
+            res = fakeaddress(self.ob, offset)
+            #res.ref() # sanity check
+            return res
         return NotImplemented
 
     def __sub__(self, other):

Modified: pypy/dist/pypy/rpython/memory/gc.py
==============================================================================
--- pypy/dist/pypy/rpython/memory/gc.py	(original)
+++ pypy/dist/pypy/rpython/memory/gc.py	Mon May 15 20:20:48 2006
@@ -168,6 +168,7 @@
     def collect(self):
         import os
         os.write(2, 'collecting... ')
+        old_malloced = self.bytes_malloced
         self.bytes_malloced = 0
         roots = self.get_roots()
         objects = self.AddressLinkedList()
@@ -202,10 +203,10 @@
             if self.is_varsize(typeid):
                 offset = self.varsize_offset_to_variable_part(
                     typeid)
+                curr += offset
                 length = (curr + self.varsize_offset_to_length(typeid)).signed[0]
                 offsets = self.varsize_offsets_to_gcpointers_in_var_part(typeid)
                 itemlength = self.varsize_item_sizes(typeid)
-                curr += offset
                 i = 0
                 while i < length:
                     item = curr + itemlength * i
@@ -243,6 +244,7 @@
             self.heap_size = curr_heap_size
         # warning, the following debug print allocates memory to manipulate
         # the strings!  so it must be at the end
+        os.write(2, "malloced before this collection %s bytes. " % old_malloced)
         os.write(2, "freed %s bytes. the heap is now %s bytes.\n" % (freed_size, curr_heap_size))
 
     STATISTICS_NUMBERS = 2

Modified: pypy/dist/pypy/rpython/memory/gctransform.py
==============================================================================
--- pypy/dist/pypy/rpython/memory/gctransform.py	(original)
+++ pypy/dist/pypy/rpython/memory/gctransform.py	Mon May 15 20:20:48 2006
@@ -744,6 +744,7 @@
             # types of the GC information tables
             OFFSETS_TO_GC_PTR = lltype.Array(lltype.Signed)
             TYPE_INFO = lltype.Struct("type_info",
+                ("isvarsize",   lltype.Bool),
                 ("fixedsize",   lltype.Signed),
                 ("ofstoptrs",   lltype.Ptr(OFFSETS_TO_GC_PTR)),
                 ("varitemsize", lltype.Signed),
@@ -754,7 +755,7 @@
             TYPE_INFO_TABLE = lltype.Array(TYPE_INFO)
 
         def q_is_varsize(typeid):
-            return gcdata.type_info_table[typeid].ofstolength != -1
+            return gcdata.type_info_table[typeid].isvarsize
 
         def q_offsets_to_gc_pointers(typeid):
             return gcdata.type_info_table[typeid].ofstoptrs
@@ -951,9 +952,11 @@
             offsets = offsets_to_gc_pointers(TYPE)
             info["ofstoptrs"] = self.offsets2table(offsets, TYPE)
             if not TYPE._is_varsize():
+                info["isvarsize"] = False
                 info["fixedsize"] = llmemory.sizeof(TYPE)
                 info["ofstolength"] = -1
             else:
+                info["isvarsize"] = True
                 info["fixedsize"] = llmemory.sizeof(TYPE, 0)
                 if isinstance(TYPE, lltype.Struct):
                     ARRAY = TYPE._flds[TYPE._arrayfld]
@@ -988,10 +991,12 @@
         if isinstance(TYPE, (lltype.GcStruct, lltype.GcArray)):
             self.get_type_id(TYPE)
         if TYPE != lltype.PyObject and find_gc_ptrs_in_type(TYPE):
+            p = lltype._ptr(lltype.Ptr(TYPE), value)
+            adr = llmemory.cast_ptr_to_adr(p)
             if isinstance(TYPE, (lltype.GcStruct, lltype.GcArray)):
-                self.static_gc_roots.append(value)
+                self.static_gc_roots.append(adr)
             else: 
-                for a in gc_pointers_inside(value, llmemory.fakeaddress(value)):
+                for a in gc_pointers_inside(value, adr):
                     self.addresses_of_static_ptrs_in_nongc.append(a)
 
     def gc_fields(self):
@@ -1050,8 +1055,8 @@
                                                 self.extra_static_slots,
                                             immortal=True)
             for i in range(len(self.static_gc_roots)):
-                c = self.static_gc_roots[i]
-                ll_static_roots[i] = llmemory.fakeaddress(c)
+                adr = self.static_gc_roots[i]
+                ll_static_roots[i] = adr
             ll_instance.inst_static_roots = ll_static_roots
 
             ll_static_roots_inside = lltype.malloc(lltype.Array(llmemory.Address),
@@ -1178,6 +1183,11 @@
                     offsets.append(baseofs)
                 else:
                     offsets.append(baseofs + s)
+        # sanity check
+        #ex = lltype.Ptr(TYPE)._example()
+        #adr = llmemory.cast_ptr_to_adr(ex)
+        #for off in offsets:
+        #    (adr + off)
     elif (isinstance(TYPE, lltype.Ptr) and TYPE._needsgc() and
           TYPE.TO is not lltype.PyObject):
         offsets.append(0)

Modified: pypy/dist/pypy/rpython/memory/test/test_transformed_gc.py
==============================================================================
--- pypy/dist/pypy/rpython/memory/test/test_transformed_gc.py	(original)
+++ pypy/dist/pypy/rpython/memory/test/test_transformed_gc.py	Mon May 15 20:20:48 2006
@@ -216,7 +216,7 @@
 
     class gcpolicy(gc.FrameworkGcPolicy):
         class transformerclass(gctransform.FrameworkGCTransformer):
-            GC_PARAMS = {'start_heap_size': 50000 } # XXX in-progress 4096 -> collection! boom
+            GC_PARAMS = {'start_heap_size': 15999 } # XXX 4096 -> collect boom
             
     def test_llinterp_lists(self):
         def malloc_a_lot():
@@ -225,16 +225,15 @@
                 i += 1
                 a = [1] * 10
                 j = 0
-                while j < 20:
+                while j < 30:
                     j += 1
                     a.append(j)
         run, statistics = self.runner(malloc_a_lot, statistics=True)
         run([])
-        allocated = statistics().item1
-        assert allocated < 16000 * INT_SIZE / 4 # xxx
+        heap_size = statistics().item0
+        assert heap_size < 16000 * INT_SIZE / 4 # xxx
 
     def test_llinterp_tuples(self):
-        #curr = simulator.current_size
         def malloc_a_lot():
             i = 0
             while i < 10:
@@ -245,9 +244,10 @@
                 while j < 20:
                     j += 1
                     b.append((1, j, i))
-        self.runner(malloc_a_lot)([])
-        #assert simulator.current_size - curr < 16000 * INT_SIZE / 4
-        #print "size before: %s, size after %s" % (curr, simulator.current_size)
+        run, statistics = self.runner(malloc_a_lot, statistics=True)
+        run([])
+        heap_size = statistics().item0
+        assert heap_size < 16000 * INT_SIZE / 4 # xxx                    
 
     def test_global_list(self):
         class Box:
@@ -265,12 +265,15 @@
             assert res == i - 1 # crashes if constants are not considered roots
             
     def test_string_concatenation(self):
-        #curr = simulator.current_size
+
         def concat(j, dummy):
             lst = []
             for i in range(j):
                 lst.append(str(i))
             return len("".join(lst))
         res = self.runner(concat, withargs=True)([100, 0])
-        #assert res == concat(100)
-        #assert simulator.current_size - curr < 16000 * INT_SIZE / 4
+        run, statistics = self.runner(concat, withargs=True, statistics=True)
+        res = run([100, 0])
+        assert res == concat(100, 0)
+        heap_size = statistics().item0
+        assert heap_size < 16000 * INT_SIZE / 4 # xxx


From pedronis at codespeak.net  Mon May 15 23:58:27 2006
From: pedronis at codespeak.net (pedronis at codespeak.net)
Date: Mon, 15 May 2006 23:58:27 +0200 (CEST)
Subject: [pypy-svn] r27258 - in pypy/dist/pypy: rpython/lltypesystem
	rpython/memory rpython/memory/test translator/c
Message-ID: <20060515215827.78B81100A4@code0.codespeak.net>

Author: pedronis
Date: Mon May 15 23:58:23 2006
New Revision: 27258

Modified:
   pypy/dist/pypy/rpython/lltypesystem/llmemory.py
   pypy/dist/pypy/rpython/lltypesystem/lltype.py
   pypy/dist/pypy/rpython/memory/gc.py
   pypy/dist/pypy/rpython/memory/gctransform.py
   pypy/dist/pypy/rpython/memory/test/test_transformed_gc.py
   pypy/dist/pypy/translator/c/gc.py
Log:
test_transformed_gc for mark-and-sweep passes on top of llinterp without simulator even if the parameters introduce
collections!

attach gc header info to prebuilt constants to allow this.

fakeadr -+0

some fixes.



Modified: pypy/dist/pypy/rpython/lltypesystem/llmemory.py
==============================================================================
--- pypy/dist/pypy/rpython/lltypesystem/llmemory.py	(original)
+++ pypy/dist/pypy/rpython/lltypesystem/llmemory.py	Mon May 15 23:58:23 2006
@@ -203,10 +203,18 @@
         try:
             headerobj = _gc_struct2header[gcptr._obj]
         except KeyError:
-            headerobj = lltype.malloc(self.minimal_layout,
-                                      immortal=True)._obj
+            # sanity checks
+            HDR = self.minimal_layout
+            gcobj = gcptr._obj
+            assert isinstance(gcobj._TYPE, lltype.GC_CONTAINER)
+            assert not gcobj._parentstructure()
+            
+            headerobj = lltype.malloc(HDR, immortal=True)._obj
+            # make uninitialized access explode
+            for fldname in HDR._names:
+                getattr(type(headerobj), fldname).__set__(headerobj, None)
             _gc_struct2header[gcptr._obj] = headerobj
-            _gc_header2struct[headerobj] = gcptr._obj
+            _gc_header2struct[headerobj] = gcobj
         p = lltype._ptr(lltype.Ptr(headerobj._TYPE), headerobj, True)
         return _obref(p)
 
@@ -284,7 +292,7 @@
 
 class fakeaddress(object):
     def __init__(self, ob, offset=None):
-        #assert not isinstance(ob, lltype._parentable) - XXX in-progress
+        assert not isinstance(ob, lltype._parentable)
         self.ob = ob or None    # replace null pointers with None
         self.offset = offset
 
@@ -306,11 +314,15 @@
             res = fakeaddress(self.ob, offset)
             #res.ref() # sanity check
             return res
+        if other == 0:
+            return self
         return NotImplemented
 
     def __sub__(self, other):
         if isinstance(other, AddressOffset):
             return self + (-other)
+        if other == 0:
+            return self
         return NotImplemented
 
     def __nonzero__(self):

Modified: pypy/dist/pypy/rpython/lltypesystem/lltype.py
==============================================================================
--- pypy/dist/pypy/rpython/lltypesystem/lltype.py	(original)
+++ pypy/dist/pypy/rpython/lltypesystem/lltype.py	Mon May 15 23:58:23 2006
@@ -769,6 +769,15 @@
     else:
         return None, None
 
+def top_container(container):
+    top_parent = container
+    while True:
+        parent = top_parent._parentstructure()
+        if parent is None:
+            break
+        top_parent = parent
+    return top_parent
+
 
 class _ptr(object):
     __slots__ = ('_TYPE', '_T', 
@@ -990,8 +999,7 @@
         obj = self._obj
         if isinstance(obj, int):
             return obj     # special case for cast_int_to_ptr() results
-        while obj._parentstructure():
-            obj = obj._parentstructure() 
+        obj = top_container(obj)
         result = id(obj)
         # assume that id() returns an addressish value which is
         # not zero and aligned to at least a multiple of 4
@@ -1406,12 +1414,8 @@
     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
+    struct = p._obj
+    top_parent = top_container(struct)
     result = getRuntimeTypeInfo(top_parent._TYPE)
     static_info = getRuntimeTypeInfo(T.TO)
     query_funcptr = getattr(static_info._obj, 'query_funcptr', None)

Modified: pypy/dist/pypy/rpython/memory/gc.py
==============================================================================
--- pypy/dist/pypy/rpython/memory/gc.py	(original)
+++ pypy/dist/pypy/rpython/memory/gc.py	Mon May 15 23:58:23 2006
@@ -203,8 +203,8 @@
             if self.is_varsize(typeid):
                 offset = self.varsize_offset_to_variable_part(
                     typeid)
-                curr += offset
                 length = (curr + self.varsize_offset_to_length(typeid)).signed[0]
+                curr += offset
                 offsets = self.varsize_offsets_to_gcpointers_in_var_part(typeid)
                 itemlength = self.varsize_item_sizes(typeid)
                 i = 0
@@ -229,7 +229,7 @@
             size = self.fixed_size(typeid)
             if self.is_varsize(typeid):
                 length = (curr + MarkSweepGC._size_gc_header + self.varsize_offset_to_length(typeid)).signed[0]
-                size += length * self.varsize_item_sizes(typeid)
+                size += self.varsize_item_sizes(typeid) * length
             estimate = raw_malloc_usage(MarkSweepGC._size_gc_header + size)
             if hdr.typeid & 1:
                 hdr.typeid = hdr.typeid & (~1)

Modified: pypy/dist/pypy/rpython/memory/gctransform.py
==============================================================================
--- pypy/dist/pypy/rpython/memory/gctransform.py	(original)
+++ pypy/dist/pypy/rpython/memory/gctransform.py	Mon May 15 23:58:23 2006
@@ -885,8 +885,8 @@
         r_gc = self.translator.rtyper.getrepr(s_gc)
         self.c_const_gc = rmodel.inputconst(r_gc, self.gcdata.gc)
 
-        gc_header_offset = self.gcdata.gc.size_gc_header()
-        HDR = self._gc_HDR = gc_header_offset.minimal_layout
+        self.gc_header_offset = self.gcdata.gc.size_gc_header()
+        HDR = self._gc_HDR = self.gc_header_offset.minimal_layout
         self._gc_fields = fields = []
         for fldname in HDR._names:
             FLDTYPE = getattr(HDR, fldname)
@@ -986,13 +986,18 @@
             return type_id
 
     def consider_constant(self, TYPE, value):
-        if id(value) not in self.seen_roots:
-            self.seen_roots[id(value)] = True
+        if id(value) in self.seen_roots:
+            return
+        self.seen_roots[id(value)] = True
+        p = lltype._ptr(lltype.Ptr(TYPE), value)
+        adr = llmemory.cast_ptr_to_adr(p)
+
         if isinstance(TYPE, (lltype.GcStruct, lltype.GcArray)):
-            self.get_type_id(TYPE)
+            typeid = self.get_type_id(TYPE)
+            if lltype.top_container(value) is value:
+                self.gcdata.gc.init_gc_object(adr-self.gc_header_offset, typeid)
+
         if TYPE != lltype.PyObject and find_gc_ptrs_in_type(TYPE):
-            p = lltype._ptr(lltype.Ptr(TYPE), value)
-            adr = llmemory.cast_ptr_to_adr(p)
             if isinstance(TYPE, (lltype.GcStruct, lltype.GcArray)):
                 self.static_gc_roots.append(adr)
             else: 
@@ -1003,11 +1008,11 @@
         return self._gc_fields
 
     def gc_field_values_for(self, obj):
+        p = lltype._ptr(lltype.Ptr(lltype.typeOf(obj)), obj)
+        adr = llmemory.cast_ptr_to_adr(p)
         HDR = self._gc_HDR
-        p_hdr = lltype.malloc(HDR, immortal=True)
-        hdr_adr = llmemory.cast_ptr_to_adr(p_hdr)
-        vals = []
-        self.gcdata.gc.init_gc_object(hdr_adr, self.get_type_id(lltype.typeOf(obj)))
+        p_hdr = llmemory.cast_adr_to_ptr(adr-self.gc_header_offset,
+                                         lltype.Ptr(HDR))
         return [getattr(p_hdr, fldname) for fldname in HDR._names]
 
     def offsets2table(self, offsets, TYPE):

Modified: pypy/dist/pypy/rpython/memory/test/test_transformed_gc.py
==============================================================================
--- pypy/dist/pypy/rpython/memory/test/test_transformed_gc.py	(original)
+++ pypy/dist/pypy/rpython/memory/test/test_transformed_gc.py	Mon May 15 23:58:23 2006
@@ -216,7 +216,7 @@
 
     class gcpolicy(gc.FrameworkGcPolicy):
         class transformerclass(gctransform.FrameworkGCTransformer):
-            GC_PARAMS = {'start_heap_size': 15999 } # XXX 4096 -> collect boom
+            GC_PARAMS = {'start_heap_size': 4096 }
             
     def test_llinterp_lists(self):
         def malloc_a_lot():

Modified: pypy/dist/pypy/translator/c/gc.py
==============================================================================
--- pypy/dist/pypy/translator/c/gc.py	(original)
+++ pypy/dist/pypy/translator/c/gc.py	Mon May 15 23:58:23 2006
@@ -3,7 +3,7 @@
 from pypy.translator.c.node import ContainerNode
 from pypy.rpython.lltypesystem.lltype import \
      typeOf, Ptr, PyObject, ContainerType, GcArray, GcStruct, \
-     RuntimeTypeInfo, getRuntimeTypeInfo
+     RuntimeTypeInfo, getRuntimeTypeInfo, top_container
 from pypy.rpython.memory import gctransform
 from pypy.rpython.lltypesystem import lltype, llmemory
 
@@ -377,12 +377,7 @@
         return defnode.db.gctransformer.gc_fields()
 
     def common_gcheader_initdata(self, defnode):
-        o = defnode.obj
-        while True:
-            n = o._parentstructure()
-            if n is None:
-                break
-            o = n
+        o = top_container(defnode.obj)
         return defnode.db.gctransformer.gc_field_values_for(o)
 
     def zero_malloc(self, TYPE, esize, eresult):


From pedronis at codespeak.net  Tue May 16 02:41:45 2006
From: pedronis at codespeak.net (pedronis at codespeak.net)
Date: Tue, 16 May 2006 02:41:45 +0200 (CEST)
Subject: [pypy-svn] r27259 - in pypy/dist/pypy/rpython/lltypesystem: . test
Message-ID: <20060516004145.78150100A4@code0.codespeak.net>

Author: pedronis
Date: Tue May 16 02:41:41 2006
New Revision: 27259

Modified:
   pypy/dist/pypy/rpython/lltypesystem/llmemory.py
   pypy/dist/pypy/rpython/lltypesystem/test/test_llmemory.py
Log:
start experimenting with primitives bump and arena to express copy collectors such that they can be run
without the simulator.



Modified: pypy/dist/pypy/rpython/lltypesystem/llmemory.py
==============================================================================
--- pypy/dist/pypy/rpython/lltypesystem/llmemory.py	(original)
+++ pypy/dist/pypy/rpython/lltypesystem/llmemory.py	Tue May 16 02:41:41 2006
@@ -480,3 +480,49 @@
         from pypy.rpython.memory.lltypelayout import convert_offset_to_int
         size = convert_offset_to_int(size)
     return size
+
+# ____________________________________________________________
+
+class _arena(object):
+
+    def __init__(self, rng):
+        self.rng = rng
+        self.items = []
+
+class ArenaItem(AddressOffset):
+    
+    def __init__(self, nr):
+        self.nr = nr
+
+    def ref(self, ref):
+        assert isinstance(ref, _obref)
+        assert isinstance(ref.ob, _arena)
+        arena = ref.ob
+        itemadr = arena.items[self.nr]
+        return itemadr.ref()
+        
+class ArenaRange(AddressOffset):
+    def __init__(self, unitsize, n):
+        self.unitsize = unitsize
+        self.n = n
+
+    def raw_malloc(self, rest):
+        assert not rest
+        return fakeaddress(_arena(self), ArenaItem(0))
+        
+def arena(TYPE, n):
+    return ArenaRange(sizeof(TYPE), n)
+
+def bump(adr, size):
+    assert isinstance(adr.ob, _arena)
+    assert isinstance(adr.offset, ArenaItem)
+    arena = adr.ob
+    nr = adr.offset.nr
+    if len(arena.items) == nr: # reserve
+        # xxx check that we are not larger than unitsize*n
+        itemadr = raw_malloc(size)
+        arena.items.append(itemadr)
+    else:
+        assert nr < len(arena.items)
+        # xxx check that size matches
+    return fakeaddress(arena, ArenaItem(nr+1))

Modified: pypy/dist/pypy/rpython/lltypesystem/test/test_llmemory.py
==============================================================================
--- pypy/dist/pypy/rpython/lltypesystem/test/test_llmemory.py	(original)
+++ pypy/dist/pypy/rpython/lltypesystem/test/test_llmemory.py	Tue May 16 02:41:41 2006
@@ -282,3 +282,23 @@
     assert p.y[7] == 18187
     py.test.raises(IndexError,
                    "(adr + offsetof(S, 'y') + itemoffsetof(A, 10)).signed[0]")
+
+def test_arena_bump_ptr():
+    S = lltype.Struct('S', ('x',lltype.Signed))
+    SPTR = lltype.Ptr(S)
+    badr = start = raw_malloc(arena(S, 4))
+    s_adr = badr
+    badr = bump(badr, sizeof(S))
+    s_ptr = cast_adr_to_ptr(s_adr, SPTR)
+    s_ptr.x = 1
+    s2_adr = badr
+    badr = bump(badr, sizeof(S))
+    s2_ptr = cast_adr_to_ptr(s2_adr, SPTR)
+    s2_ptr.x = 2
+    badr = start
+    s_ptr = cast_adr_to_ptr(badr, SPTR)
+    assert s_ptr.x == 1
+    badr = bump(badr, sizeof(S))
+    s2_ptr = cast_adr_to_ptr(badr, SPTR)
+    assert s2_ptr.x == 2
+    # release(start)


From hpk at codespeak.net  Tue May 16 09:59:30 2006
From: hpk at codespeak.net (hpk at codespeak.net)
Date: Tue, 16 May 2006 09:59:30 +0200 (CEST)
Subject: [pypy-svn] r27260 - pypy/extradoc/sprintinfo/ddorf2006
Message-ID: <20060516075930.B0E5710080@code0.codespeak.net>

Author: hpk
Date: Tue May 16 09:59:28 2006
New Revision: 27260

Modified:
   pypy/extradoc/sprintinfo/ddorf2006/people.txt
Log:
arriving on the 1st june already, probably


Modified: pypy/extradoc/sprintinfo/ddorf2006/people.txt
==============================================================================
--- pypy/extradoc/sprintinfo/ddorf2006/people.txt	(original)
+++ pypy/extradoc/sprintinfo/ddorf2006/people.txt	Tue May 16 09:59:28 2006
@@ -10,7 +10,7 @@
 ==================== ============== =====================
 Michael Hudson       ?              private
 Armin Rigo           ?              private
-Holger Krekel        2nd-9th        ?
+Holger Krekel        1st-9th        ?
 Carl Friedrich Bolz  nope :-)       private
 Eric van Riet Paap   ?              ?
 ==================== ============== =====================


From antocuni at codespeak.net  Tue May 16 10:52:06 2006
From: antocuni at codespeak.net (antocuni at codespeak.net)
Date: Tue, 16 May 2006 10:52:06 +0200 (CEST)
Subject: [pypy-svn] r27261 - pypy/dist/pypy/rpython/ootypesystem/test
Message-ID: <20060516085206.E0AF31006E@code0.codespeak.net>

Author: antocuni
Date: Tue May 16 10:52:01 2006
New Revision: 27261

Modified:
   pypy/dist/pypy/rpython/ootypesystem/test/test_ooann.py
   pypy/dist/pypy/rpython/ootypesystem/test/test_oortype.py
Log:
Added a failing test about 'assert' to test_oortype.py.



Modified: pypy/dist/pypy/rpython/ootypesystem/test/test_ooann.py
==============================================================================
--- pypy/dist/pypy/rpython/ootypesystem/test/test_ooann.py	(original)
+++ pypy/dist/pypy/rpython/ootypesystem/test/test_ooann.py	Tue May 16 10:52:01 2006
@@ -2,6 +2,7 @@
 from pypy.annotation import model as annmodel
 from pypy.objspace.flow import FlowObjSpace
 from pypy.annotation.annrpython import RPythonAnnotator
+import exceptions
 
 
 def test_simple_new():
@@ -225,4 +226,3 @@
     a = RPythonAnnotator()
     s = a.build_types(oof, [])
     assert isinstance(s, annmodel.SomeBuiltin)
-

Modified: pypy/dist/pypy/rpython/ootypesystem/test/test_oortype.py
==============================================================================
--- pypy/dist/pypy/rpython/ootypesystem/test/test_oortype.py	(original)
+++ pypy/dist/pypy/rpython/ootypesystem/test/test_oortype.py	Tue May 16 10:52:01 2006
@@ -214,3 +214,9 @@
 
     res = interpret(oof, [False], type_system='ootype')
     assert isinstance(res, ootype._null_string)
+
+def test_assert():
+    def oof(b):
+        assert b
+
+    interpret(oof, [True], type_system='ootype')


From arigo at codespeak.net  Tue May 16 11:27:01 2006
From: arigo at codespeak.net (arigo at codespeak.net)
Date: Tue, 16 May 2006 11:27:01 +0200 (CEST)
Subject: [pypy-svn] r27263 - in pypy/dist/pypy/objspace: . constraint/test
Message-ID: <20060516092701.C69E910070@code0.codespeak.net>

Author: arigo
Date: Tue May 16 11:26:59 2006
New Revision: 27263

Modified:
   pypy/dist/pypy/objspace/constraint/test/test_btree.py
   pypy/dist/pypy/objspace/constraint/test/test_distributor.py
   pypy/dist/pypy/objspace/constraint/test/test_solver.py
   pypy/dist/pypy/objspace/logic.py
Log:
Fixes for long-standing failures in objspace/constraint:

* don't 'import pypy' at app-level!  It's not supposed to be
  importable like this, and it's not in the app-level path
  unless put there with a PYTHONPATH env var.

* skip a test that consistently fail.  For all I can tell it
  might be testing an implementation detail that changed.



Modified: pypy/dist/pypy/objspace/constraint/test/test_btree.py
==============================================================================
--- pypy/dist/pypy/objspace/constraint/test/test_btree.py	(original)
+++ pypy/dist/pypy/objspace/constraint/test/test_btree.py	Tue May 16 11:26:59 2006
@@ -1,4 +1,4 @@
-class AppTest_BTree(object):
+class TestBTree(object):
 
 
     def test_everything_at_once(self):

Modified: pypy/dist/pypy/objspace/constraint/test/test_distributor.py
==============================================================================
--- pypy/dist/pypy/objspace/constraint/test/test_distributor.py	(original)
+++ pypy/dist/pypy/objspace/constraint/test/test_distributor.py	Tue May 16 11:26:59 2006
@@ -21,6 +21,7 @@
         z = spc.var('z', FiniteDomain([1, 2, 3]))
         d = NaiveDistributor()
         d.distribute(spc, 2)
+        skip("XXX fix this test?")
         assert spc.dom(y) == FiniteDomain([2])
         d.distribute(spc, 1)
         assert spc.dom(y) == FiniteDomain([2])

Modified: pypy/dist/pypy/objspace/constraint/test/test_solver.py
==============================================================================
--- pypy/dist/pypy/objspace/constraint/test/test_solver.py	(original)
+++ pypy/dist/pypy/objspace/constraint/test/test_solver.py	Tue May 16 11:26:59 2006
@@ -6,7 +6,7 @@
         cls.space = gettestobjspace('logic')
 
     def test_instantiate(self):
-        from pypy.objspace.constraint.applevel import solver, problems
+        import solver, problems
         spc = newspace()
 
         spc.define_problem(problems.conference_scheduling)
@@ -15,7 +15,7 @@
         assert str(type(sols)) == ""
 
     def test_solve(self):
-        from pypy.objspace.constraint.applevel import solver, problems
+        import solver, problems
         spc = newspace()
 
         spc.define_problem(problems.conference_scheduling)

Modified: pypy/dist/pypy/objspace/logic.py
==============================================================================
--- pypy/dist/pypy/objspace/logic.py	(original)
+++ pypy/dist/pypy/objspace/logic.py	Tue May 16 11:26:59 2006
@@ -847,8 +847,13 @@
                  space.wrap(distributor.app_make_split_distributor))
     space.setitem(space.builtin.w_dict, space.wrap('DichotomyDistributor'),
                  space.wrap(distributor.app_make_dichotomy_distributor))
-    
-    
+    #-- path to the applevel modules --
+    import pypy.objspace.constraint
+    import os
+    dir = os.path.dirname(pypy.objspace.constraint.__file__)
+    dir = os.path.join(dir, 'applevel')
+    space.call_method(space.sys.get('path'), 'append', space.wrap(dir))
+
     if USE_COROUTINES:
         import os
         def exitfunc():


From ericvrp at codespeak.net  Tue May 16 13:39:47 2006
From: ericvrp at codespeak.net (ericvrp at codespeak.net)
Date: Tue, 16 May 2006 13:39:47 +0200 (CEST)
Subject: [pypy-svn] r27266 - pypy/dist/pypy/module/_pickle_support
Message-ID: <20060516113947.17C3910072@code0.codespeak.net>

Author: ericvrp
Date: Tue May 16 13:39:46 2006
New Revision: 27266

Modified:
   pypy/dist/pypy/module/_pickle_support/maker.py
Log:
temp check-in for debugging

Modified: pypy/dist/pypy/module/_pickle_support/maker.py
==============================================================================
--- pypy/dist/pypy/module/_pickle_support/maker.py	(original)
+++ pypy/dist/pypy/module/_pickle_support/maker.py	Tue May 16 13:39:46 2006
@@ -36,20 +36,26 @@
 method_new.unwrap_spec = [ObjSpace, Arguments]
 
 #XXX this does not work yet
-def dictiter_new(space, w_dictitertype, __args__):
-    raise Exception('No dictiter_new (pickle support) yet')
-    print "dictiter_new here 1)", space, w_dictitertype
-    #w_type = space.gettypeobject(dictiter_typedef)
-    #print "dictiter_new here 2)", w_type
-    #a = space.call_args(w_type, __args__)
-    #print "dictiter_new here 3)", a
-    #return a
-    from pypy.objspace.std.dictobject import W_DictIterObject
-    w_obj = space.allocate_instance(W_DictIterObject, w_dictitertype)
-    print "dictiter_new here 2)", w_obj
-    W_DictIterObject.__init__(w_obj, space)
-    print "dictiter_new here 3)", w_obj
-    return w_obj
+def dictiter_new(space, w_dictitertype, __args__=None):
+    #raise Exception('No dictiter_new (pickle support) yet')
+    print "dictiter_new here 0)", space, w_dictitertype, __args__
+    print "XXX", str(dictiter_typedef)
+    if False:
+        w_type = space.gettypeobject(dictiter_typedef)
+        print "dictiter_new here 2)", w_type
+        a = space.call_args(w_type, __args__)
+        print "dictiter_new here 3)", a
+        return a
+    else:
+        from pypy.objspace.std.dictobject import W_DictIterObject
+        print "dictiter_new here 1)", space, w_dictitertype, __args__
+        #import pdb;pdb.set_trace()
+        if space.is_true(space.issubtype(w_dictitertype, W_DictIterObject)):
+            w_obj = space.allocate_instance(W_DictIterObject, w_dictitertype)
+            print "dictiter_new here 2)", w_obj
+            W_DictIterObject.__init__(w_obj, space)
+            print "dictiter_new here 3)", w_obj
+            return w_obj
 dictiter_new.unwrap_spec = [ObjSpace, W_Root, Arguments]
 
 #XXX this doesn't work either


From ericvrp at codespeak.net  Tue May 16 13:42:31 2006
From: ericvrp at codespeak.net (ericvrp at codespeak.net)
Date: Tue, 16 May 2006 13:42:31 +0200 (CEST)
Subject: [pypy-svn] r27268 - pypy/dist/pypy/module/_pickle_support
Message-ID: <20060516114231.16D9410076@code0.codespeak.net>

Author: ericvrp
Date: Tue May 16 13:42:30 2006
New Revision: 27268

Modified:
   pypy/dist/pypy/module/_pickle_support/maker.py
Log:
Do not remove this raise or else translation will fail


Modified: pypy/dist/pypy/module/_pickle_support/maker.py
==============================================================================
--- pypy/dist/pypy/module/_pickle_support/maker.py	(original)
+++ pypy/dist/pypy/module/_pickle_support/maker.py	Tue May 16 13:42:30 2006
@@ -37,7 +37,7 @@
 
 #XXX this does not work yet
 def dictiter_new(space, w_dictitertype, __args__=None):
-    #raise Exception('No dictiter_new (pickle support) yet')
+    raise Exception('No dictiter_new (pickle support) yet')
     print "dictiter_new here 0)", space, w_dictitertype, __args__
     print "XXX", str(dictiter_typedef)
     if False:


From mwh at codespeak.net  Tue May 16 13:47:09 2006
From: mwh at codespeak.net (mwh at codespeak.net)
Date: Tue, 16 May 2006 13:47:09 +0200 (CEST)
Subject: [pypy-svn] r27269 - in pypy/dist/pypy: annotation rpython
	rpython/lltypesystem rpython/lltypesystem/test
Message-ID: <20060516114709.DB2751006F@code0.codespeak.net>

Author: mwh
Date: Tue May 16 13:47:06 2006
New Revision: 27269

Modified:
   pypy/dist/pypy/annotation/builtin.py
   pypy/dist/pypy/annotation/model.py
   pypy/dist/pypy/rpython/llinterp.py
   pypy/dist/pypy/rpython/lltypesystem/llmemory.py
   pypy/dist/pypy/rpython/lltypesystem/lloperation.py
   pypy/dist/pypy/rpython/lltypesystem/test/test_llmemory.py
   pypy/dist/pypy/rpython/raddress.py
   pypy/dist/pypy/rpython/rbuiltin.py
Log:
add a weakgcaddress primitive and casts to and from pointers.  and associated
hair.

the purpose of this is to have a type that will be edited as necessary by a
moving GC, but not treated as keeping the addressed object alive.


Modified: pypy/dist/pypy/annotation/builtin.py
==============================================================================
--- pypy/dist/pypy/annotation/builtin.py	(original)
+++ pypy/dist/pypy/annotation/builtin.py	Tue May 16 13:47:06 2006
@@ -6,7 +6,7 @@
 from pypy.annotation.model import SomeInteger, SomeObject, SomeChar, SomeBool
 from pypy.annotation.model import SomeString, SomeTuple, SomeSlice
 from pypy.annotation.model import SomeUnicodeCodePoint, SomeAddress
-from pypy.annotation.model import SomeFloat, unionof
+from pypy.annotation.model import SomeFloat, SomeWeakGcAddress, unionof
 from pypy.annotation.model import SomePBC, SomeInstance, SomeDict
 from pypy.annotation.model import SomeExternalObject
 from pypy.annotation.model import annotation_to_lltype, lltype_to_annotation, ll_to_annotation
@@ -305,6 +305,13 @@
     assert s_type.is_constant()
     return SomePtr(s_type.const)
 
+def llmemory_cast_ptr_to_weakadr(s):
+    return SomeWeakGcAddress()
+
+def llmemory_cast_weakadr_to_ptr(s, s_type):
+    assert s_type.is_constant()
+    return SomePtr(s_type.const)
+
 def llmemory_cast_adr_to_int(s):
     return SomeInteger() # xxx
 
@@ -353,6 +360,8 @@
 BUILTIN_ANALYZERS[pypy.rpython.lltypesystem.llmemory.cast_ptr_to_adr] = llmemory_cast_ptr_to_adr
 BUILTIN_ANALYZERS[pypy.rpython.lltypesystem.llmemory.cast_adr_to_ptr] = llmemory_cast_adr_to_ptr
 BUILTIN_ANALYZERS[pypy.rpython.lltypesystem.llmemory.cast_adr_to_int] = llmemory_cast_adr_to_int
+BUILTIN_ANALYZERS[pypy.rpython.lltypesystem.llmemory.cast_ptr_to_weakadr] = llmemory_cast_ptr_to_weakadr
+BUILTIN_ANALYZERS[pypy.rpython.lltypesystem.llmemory.cast_weakadr_to_ptr] = llmemory_cast_weakadr_to_ptr
 BUILTIN_ANALYZERS[pypy.rpython.rstack.yield_current_frame_to_caller] = (
     rstack_yield_current_frame_to_caller)
 

Modified: pypy/dist/pypy/annotation/model.py
==============================================================================
--- pypy/dist/pypy/annotation/model.py	(original)
+++ pypy/dist/pypy/annotation/model.py	Tue May 16 13:47:06 2006
@@ -461,6 +461,8 @@
     def can_be_none(self):
         return False
 
+class SomeWeakGcAddress(SomeObject):
+    immutable = True
 
 # The following class is used to annotate the intermediate value that
 # appears in expressions of the form:

Modified: pypy/dist/pypy/rpython/llinterp.py
==============================================================================
--- pypy/dist/pypy/rpython/llinterp.py	(original)
+++ pypy/dist/pypy/rpython/llinterp.py	Tue May 16 13:47:06 2006
@@ -334,7 +334,8 @@
         vals = [self.getval(x) for x in operation.args]
         # XXX these special cases DO pile up, do something better here
         if operation.opname in ['cast_pointer', 'ooupcast', 'oodowncast',
-                                'cast_adr_to_ptr', 'cast_int_to_ptr',
+                                'cast_adr_to_ptr', 'cast_weakadr_to_ptr',
+                                'cast_int_to_ptr',
                                 'cast_opaque_ptr', 'unsafe_call',
                                 'cast_primitive']:
             vals.insert(0, operation.result.concretetype)
@@ -616,6 +617,14 @@
         assert checkadr(adr)
         return llmemory.cast_adr_to_int(adr)
 
+    def op_cast_ptr_to_weakadr(self, ptr):
+        assert checkptr(ptr)
+        return llmemory.cast_ptr_to_weakadr(ptr)
+
+    def op_cast_weakadr_to_ptr(self, TYPE, wadr):
+        assert lltype.typeOf(wadr) == llmemory.WeakGcAddress
+        return llmemory.cast_weakadr_to_ptr(wadr, TYPE)
+
     def op_cast_int_to_float(self, i):
         assert type(i) is int
         return float(i)

Modified: pypy/dist/pypy/rpython/lltypesystem/llmemory.py
==============================================================================
--- pypy/dist/pypy/rpython/lltypesystem/llmemory.py	(original)
+++ pypy/dist/pypy/rpython/lltypesystem/llmemory.py	Tue May 16 13:47:06 2006
@@ -463,6 +463,35 @@
 # ____________________________________________________________
 
 import weakref
+
+class fakeweakaddress(object):
+    def __init__(self, ob):
+        if ob is not None:
+            self.ref = weakref.ref(ob)
+        else:
+            self.ref = None
+    def get(self):
+        if self.ref is None:
+            raise NullAddressError
+        ob = self.ref()
+        if ob is None:
+            raise NullAddressError
+        return ob
+
+WeakGcAddress = lltype.Primitive("WeakGcAddress",
+                                 fakeweakaddress(None))
+
+def cast_ptr_to_weakadr(obj):
+    assert isinstance(lltype.typeOf(obj), lltype.Ptr)
+    return fakeweakaddress(obj)
+
+def cast_weakadr_to_ptr(adr, EXPECTED_TYPE):
+    return adr.get()
+
+fakeweakaddress._TYPE = WeakGcAddress
+
+# ____________________________________________________________
+
 _gc_struct2header = weakref.WeakKeyDictionary()
 _gc_header2struct = weakref.WeakKeyDictionary()
 

Modified: pypy/dist/pypy/rpython/lltypesystem/lloperation.py
==============================================================================
--- pypy/dist/pypy/rpython/lltypesystem/lloperation.py	(original)
+++ pypy/dist/pypy/rpython/lltypesystem/lloperation.py	Tue May 16 13:47:06 2006
@@ -301,6 +301,8 @@
     'adr_ge':               LLOp(canfold=True),
     'cast_ptr_to_adr':      LLOp(canfold=True),
     'cast_adr_to_ptr':      LLOp(canfold=True),
+    'cast_ptr_to_weakadr':  LLOp(canfold=True),
+    'cast_weakadr_to_ptr':  LLOp(canfold=True),
     'cast_adr_to_int':      LLOp(canfold=True),
 
     # __________ GC operations __________

Modified: pypy/dist/pypy/rpython/lltypesystem/test/test_llmemory.py
==============================================================================
--- pypy/dist/pypy/rpython/lltypesystem/test/test_llmemory.py	(original)
+++ pypy/dist/pypy/rpython/lltypesystem/test/test_llmemory.py	Tue May 16 13:47:06 2006
@@ -98,6 +98,18 @@
     res = interpret(f, [])
     assert res
 
+def test_weak_casts():
+    from pypy.rpython.memory.test.test_llinterpsim import interpret
+    S = lltype.GcStruct("S", ("x", lltype.Signed))
+    Sptr = lltype.Ptr(S)
+    def f():
+        s1 = lltype.malloc(S)
+        adr = cast_ptr_to_weakadr(s1)
+        s2 = cast_weakadr_to_ptr(adr, Sptr)
+        return s1 == s2
+    res = interpret(f, [])
+    assert res
+
 def test_fakeaccessor():
     S = lltype.GcStruct("S", ("x", lltype.Signed), ("y", lltype.Signed))
     s = lltype.malloc(S)

Modified: pypy/dist/pypy/rpython/raddress.py
==============================================================================
--- pypy/dist/pypy/rpython/raddress.py	(original)
+++ pypy/dist/pypy/rpython/raddress.py	Tue May 16 13:47:06 2006
@@ -2,7 +2,8 @@
 from pypy.annotation.pairtype import pairtype
 from pypy.annotation import model as annmodel
 from pypy.rpython.memory.lladdress import _address
-from pypy.rpython.lltypesystem.llmemory import NULL, Address, cast_adr_to_int
+from pypy.rpython.lltypesystem.llmemory import NULL, Address, \
+     cast_adr_to_int, WeakGcAddress
 from pypy.rpython.rmodel import Repr, IntegerRepr
 from pypy.rpython.rptr import PtrRepr
 from pypy.rpython.lltypesystem import lltype
@@ -14,6 +15,13 @@
     def rtyper_makekey(self):
         return self.__class__,
 
+class __extend__(annmodel.SomeWeakGcAddress):
+    def rtyper_makerepr(self, rtyper):
+        return weakgcaddress_repr
+    
+    def rtyper_makekey(self):
+        return self.__class__,
+
 class __extend__(annmodel.SomeTypedAddressAccess):
     def rtyper_makerepr(self, rtyper):
         return TypedAddressAccessRepr(self.type)
@@ -128,3 +136,8 @@
 
     def convert_from_to((r_ptr, r_addr), v, llops):
         return llops.genop('cast_ptr_to_adr', [v], resulttype=Address)
+
+class WeakGcAddressRepr(Repr):
+    lowleveltype = WeakGcAddress
+
+weakgcaddress_repr = WeakGcAddressRepr()

Modified: pypy/dist/pypy/rpython/rbuiltin.py
==============================================================================
--- pypy/dist/pypy/rpython/rbuiltin.py	(original)
+++ pypy/dist/pypy/rpython/rbuiltin.py	Tue May 16 13:47:06 2006
@@ -594,7 +594,23 @@
     return hop.genop('cast_adr_to_int', [adr],
                      resulttype = lltype.Signed)
 
+def rtype_cast_ptr_to_weakadr(hop):
+    vlist = hop.inputargs(hop.args_r[0])
+    assert isinstance(vlist[0].concretetype, lltype.Ptr)
+    hop.exception_cannot_occur()
+    return hop.genop('cast_ptr_to_weakadr', vlist,
+                     resulttype = llmemory.WeakGcAddress)
+
+def rtype_cast_weakadr_to_ptr(hop):
+    assert isinstance(hop.args_r[0], raddress.WeakGcAddressRepr)
+    adr, TYPE = hop.inputargs(hop.args_r[0], lltype.Void)
+    hop.exception_cannot_occur()
+    return hop.genop('cast_weakadr_to_ptr', [adr],
+                     resulttype = TYPE.value)
+
 BUILTIN_TYPER[llmemory.cast_ptr_to_adr] = rtype_cast_ptr_to_adr
 BUILTIN_TYPER[llmemory.cast_adr_to_ptr] = rtype_cast_adr_to_ptr
 BUILTIN_TYPER[llmemory.cast_adr_to_int] = rtype_cast_adr_to_int
+BUILTIN_TYPER[llmemory.cast_ptr_to_weakadr] = rtype_cast_ptr_to_weakadr
+BUILTIN_TYPER[llmemory.cast_weakadr_to_ptr] = rtype_cast_weakadr_to_ptr
 


From arigo at codespeak.net  Tue May 16 13:50:07 2006
From: arigo at codespeak.net (arigo at codespeak.net)
Date: Tue, 16 May 2006 13:50:07 +0200 (CEST)
Subject: [pypy-svn] r27270 - in pypy/dist/pypy/rpython: lltypesystem
	lltypesystem/test memory/test
Message-ID: <20060516115007.CC02C10078@code0.codespeak.net>

Author: arigo
Date: Tue May 16 13:50:05 2006
New Revision: 27270

Modified:
   pypy/dist/pypy/rpython/lltypesystem/llmemory.py
   pypy/dist/pypy/rpython/lltypesystem/lltype.py
   pypy/dist/pypy/rpython/lltypesystem/test/test_llmemory.py
   pypy/dist/pypy/rpython/memory/test/test_transformed_gc.py
Log:
Normalize addresses, so that the address of a parent structure is
completely equivalent to the address of its first inlined substructure;
similarily, the address of an opaque that hides a structure is replaced
by the address of that structure.



Modified: pypy/dist/pypy/rpython/lltypesystem/llmemory.py
==============================================================================
--- pypy/dist/pypy/rpython/lltypesystem/llmemory.py	(original)
+++ pypy/dist/pypy/rpython/lltypesystem/llmemory.py	Tue May 16 13:50:05 2006
@@ -74,7 +74,8 @@
 
     def ref(self, containerref):
         struct = containerref.get()
-        assert lltype.typeOf(struct).TO == self.TYPE
+        if lltype.typeOf(struct).TO != self.TYPE:
+            struct = lltype.cast_pointer(lltype.Ptr(self.TYPE), struct)
         return _structfieldref(struct, self.fldname)
 
     def raw_malloc(self, rest, parenttype=None):
@@ -200,21 +201,7 @@
 
     def ref(self, gcptrref):
         gcptr = gcptrref.get()
-        try:
-            headerobj = _gc_struct2header[gcptr._obj]
-        except KeyError:
-            # sanity checks
-            HDR = self.minimal_layout
-            gcobj = gcptr._obj
-            assert isinstance(gcobj._TYPE, lltype.GC_CONTAINER)
-            assert not gcobj._parentstructure()
-            
-            headerobj = lltype.malloc(HDR, immortal=True)._obj
-            # make uninitialized access explode
-            for fldname in HDR._names:
-                getattr(type(headerobj), fldname).__set__(headerobj, None)
-            _gc_struct2header[gcptr._obj] = headerobj
-            _gc_header2struct[headerobj] = gcobj
+        headerobj = getgcheaderobj(self.minimal_layout, gcptr._obj)
         p = lltype._ptr(lltype.Ptr(headerobj._TYPE), headerobj, True)
         return _obref(p)
 
@@ -291,9 +278,10 @@
 # -------------------------------------------------------------
 
 class fakeaddress(object):
+    # NOTE: the 'ob' in the addresses must be normalized.
+    # Use cast_ptr_to_adr() instead of directly fakeaddress() if unsure.
     def __init__(self, ob, offset=None):
-        assert not isinstance(ob, lltype._parentable)
-        self.ob = ob or None    # replace null pointers with None
+        self.ob = ob
         self.offset = offset
 
     def __repr__(self):
@@ -312,7 +300,7 @@
             else:
                 offset = self.offset + other
             res = fakeaddress(self.ob, offset)
-            #res.ref() # sanity check
+            res.ref() # sanity check
             return res
         if other == 0:
             return self
@@ -436,7 +424,7 @@
 
     def convert(self, value):
         if isinstance(value, lltype._ptr):
-            return fakeaddress(value)
+            return value._cast_to_adr()
         elif lltype.typeOf(value) == Address:
             return value
         else:
@@ -495,6 +483,25 @@
 _gc_struct2header = weakref.WeakKeyDictionary()
 _gc_header2struct = weakref.WeakKeyDictionary()
 
+def getgcheaderobj(HDR, gcobj):
+    # XXX! this doesn't work if we use different HDRs in different tests
+    # for the same constants
+    try:
+        headerobj = _gc_struct2header[gcobj]
+    except KeyError:
+        # sanity checks
+        assert isinstance(gcobj._TYPE, lltype.GC_CONTAINER)
+        assert not isinstance(gcobj._TYPE, lltype.GcOpaqueType)
+        assert not gcobj._parentstructure()
+
+        headerobj = lltype.malloc(HDR, immortal=True)._obj
+        # make uninitialized access explode
+        for fldname in HDR._names:
+            getattr(type(headerobj), fldname).__set__(headerobj, None)
+        _gc_struct2header[gcobj] = headerobj
+        _gc_header2struct[headerobj] = gcobj
+    return headerobj
+
 def raw_malloc(size):
     if not isinstance(size, AddressOffset):
         raise NotImplementedError(size)

Modified: pypy/dist/pypy/rpython/lltypesystem/lltype.py
==============================================================================
--- pypy/dist/pypy/rpython/lltypesystem/lltype.py	(original)
+++ pypy/dist/pypy/rpython/lltypesystem/lltype.py	Tue May 16 13:50:05 2006
@@ -778,6 +778,36 @@
         top_parent = parent
     return top_parent
 
+def normalizeptr(p):
+    # If p is a pointer, returns the same pointer casted to the largest
+    # containing structure (for the cast where p points to the header part).
+    # Also un-hides pointers to opaque.  Null pointers become None.
+    assert not isinstance(p, _parentable)  # pointer or primitive
+    T = typeOf(p)
+    if not isinstance(T, Ptr):
+        return p      # primitive
+    if not p:
+        return None   # null pointer
+    # - if p is an opaque pointer containing a normal Struct/GcStruct,
+    #   unwrap it now
+    if isinstance(T.TO, OpaqueType) and hasattr(p._obj, 'container'):
+        T = Ptr(typeOf(p._obj.container))
+        p = cast_opaque_ptr(T, p)
+    # - if p points to the first inlined substructure of a structure,
+    #   make it point to the whole (larger) structure instead
+    container = p._obj
+    while True:
+        parent, index = parentlink(container)
+        if parent is None:
+            break
+        T = typeOf(parent)
+        if not isinstance(T, Struct) or T._first_struct()[0] != index:
+            break
+        container = parent
+    if container is not p._obj:
+        p = _ptr(Ptr(T), container, p._solid)
+    return p
+
 
 class _ptr(object):
     __slots__ = ('_TYPE', '_T', 
@@ -1012,12 +1042,12 @@
             # return an address built as an offset in the whole array
             parent, parentindex = parentlink(self._obj)
             T = typeOf(parent)
-            addr = llmemory.fakeaddress(_ptr(Ptr(T), parent))
+            addr = llmemory.fakeaddress(normalizeptr(_ptr(Ptr(T), parent)))
             addr += llmemory.itemoffsetof(T, parentindex)
             return addr
         else:
             # normal case
-            return llmemory.fakeaddress(self)
+            return llmemory.fakeaddress(normalizeptr(self))
 
 assert not '__dict__' in dir(_ptr)
 

Modified: pypy/dist/pypy/rpython/lltypesystem/test/test_llmemory.py
==============================================================================
--- pypy/dist/pypy/rpython/lltypesystem/test/test_llmemory.py	(original)
+++ pypy/dist/pypy/rpython/lltypesystem/test/test_llmemory.py	Tue May 16 13:50:05 2006
@@ -295,6 +295,27 @@
     py.test.raises(IndexError,
                    "(adr + offsetof(S, 'y') + itemoffsetof(A, 10)).signed[0]")
 
+def test_inlined_substruct():
+    T = lltype.Struct('T', ('x', lltype.Signed))
+    S1 = lltype.GcStruct('S1', ('t1', T), ('t2', T))
+    S = lltype.GcStruct('S', ('header', S1), ('t', T))
+
+    s = lltype.malloc(S)
+    s.header.t1.x = 1
+    s.header.t2.x = 2
+    s.t.x = 3
+
+    for adr in [cast_ptr_to_adr(s), cast_ptr_to_adr(s.header)]:
+        assert (adr + offsetof(S, 'header')
+                    + offsetof(S1, 't1')
+                    + offsetof(T, 'x')).signed[0] == 1
+        assert (adr + offsetof(S1, 't1')
+                    + offsetof(T, 'x')).signed[0] == 1
+        assert (adr + offsetof(S1, 't2')
+                    + offsetof(T, 'x')).signed[0] == 2
+        assert (adr + offsetof(S, 't')
+                    + offsetof(T, 'x')).signed[0] == 3
+
 def test_arena_bump_ptr():
     S = lltype.Struct('S', ('x',lltype.Signed))
     SPTR = lltype.Ptr(S)

Modified: pypy/dist/pypy/rpython/memory/test/test_transformed_gc.py
==============================================================================
--- pypy/dist/pypy/rpython/memory/test/test_transformed_gc.py	(original)
+++ pypy/dist/pypy/rpython/memory/test/test_transformed_gc.py	Tue May 16 13:50:05 2006
@@ -228,6 +228,7 @@
                 while j < 30:
                     j += 1
                     a.append(j)
+            return 0
         run, statistics = self.runner(malloc_a_lot, statistics=True)
         run([])
         heap_size = statistics().item0
@@ -244,6 +245,7 @@
                 while j < 20:
                     j += 1
                     b.append((1, j, i))
+            return 0
         run, statistics = self.runner(malloc_a_lot, statistics=True)
         run([])
         heap_size = statistics().item0
@@ -277,3 +279,10 @@
         assert res == concat(100, 0)
         heap_size = statistics().item0
         assert heap_size < 16000 * INT_SIZE / 4 # xxx
+
+
+class INPROGRESS_TestStacklessMarkSweepGC(TestMarkSweepGC):
+
+    class gcpolicy(gc.StacklessFrameworkGcPolicy):
+        class transformerclass(gctransform.StacklessFrameworkGCTransformer):
+            GC_PARAMS = {'start_heap_size': 4096 }


From antocuni at codespeak.net  Tue May 16 14:12:32 2006
From: antocuni at codespeak.net (antocuni at codespeak.net)
Date: Tue, 16 May 2006 14:12:32 +0200 (CEST)
Subject: [pypy-svn] r27271 - in pypy/dist/pypy: annotation rpython
	rpython/lltypesystem rpython/ootypesystem rpython/test
Message-ID: <20060516121232.3CF2B1007C@code0.codespeak.net>

Author: antocuni
Date: Tue May 16 14:12:17 2006
New Revision: 27271

Modified:
   pypy/dist/pypy/annotation/builtin.py
   pypy/dist/pypy/rpython/llinterp.py
   pypy/dist/pypy/rpython/lltypesystem/rstr.py
   pypy/dist/pypy/rpython/ootypesystem/ootype.py
   pypy/dist/pypy/rpython/ootypesystem/rbuiltin.py
   pypy/dist/pypy/rpython/ootypesystem/rclass.py
   pypy/dist/pypy/rpython/ootypesystem/rlist.py
   pypy/dist/pypy/rpython/ootypesystem/rstr.py
   pypy/dist/pypy/rpython/rstr.py
   pypy/dist/pypy/rpython/test/test_rstr.py
Log:
Added support for string formatting in ootypesystem.



Modified: pypy/dist/pypy/annotation/builtin.py
==============================================================================
--- pypy/dist/pypy/annotation/builtin.py	(original)
+++ pypy/dist/pypy/annotation/builtin.py	Tue May 16 14:12:17 2006
@@ -521,9 +521,9 @@
     assert isinstance(i, SomeOOInstance)
     return SomeInteger()
 
-def oostring(obj):
-    assert (isinstance(obj, (SomeInteger, SomeChar)) or
-            isinstance(obj, SomeOOInstance) and obj.ootype is ootype.String)
+def oostring(obj, base):
+    assert isinstance(obj, (SomeInteger, SomeChar, SomeOOInstance))
+    assert isinstance(base, SomeInteger)
     return SomeOOInstance(ootype.String)
 
 BUILTIN_ANALYZERS[ootype.instanceof] = instanceof

Modified: pypy/dist/pypy/rpython/llinterp.py
==============================================================================
--- pypy/dist/pypy/rpython/llinterp.py	(original)
+++ pypy/dist/pypy/rpython/llinterp.py	Tue May 16 14:12:17 2006
@@ -1020,8 +1020,8 @@
     def op_ooidentityhash(self, inst):
         return ootype.ooidentityhash(inst)
 
-    def op_oostring(self, obj):
-        return ootype.oostring(obj)
+    def op_oostring(self, obj, base):
+        return ootype.oostring(obj, base)
 
 class Tracer(object):
     Counter = 0

Modified: pypy/dist/pypy/rpython/lltypesystem/rstr.py
==============================================================================
--- pypy/dist/pypy/rpython/lltypesystem/rstr.py	(original)
+++ pypy/dist/pypy/rpython/lltypesystem/rstr.py	Tue May 16 14:12:17 2006
@@ -648,31 +648,6 @@
         return hop.gendirectcall(cls.ll_join_strs, size, vtemp)
     do_stringformat = classmethod(do_stringformat)
 
-    def parse_fmt_string(fmt):
-        # we support x, d, s, f, [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 = ''
-                if f not in 'xdosrf':
-                    raise TyperError("Unsupported formatting specifier: %r in %r" % (f, fmt))
-
-                r.append((f,))
-            else:
-                curstr += c
-        if curstr:
-            r.append(curstr)
-        return r
 
 
 

Modified: pypy/dist/pypy/rpython/ootypesystem/ootype.py
==============================================================================
--- pypy/dist/pypy/rpython/ootypesystem/ootype.py	(original)
+++ pypy/dist/pypy/rpython/ootypesystem/ootype.py	Tue May 16 14:12:17 2006
@@ -1142,8 +1142,20 @@
     assert isinstance(typeOf(inst), (Instance, Record))
     return inst._identityhash()
 
-def oostring(obj):
-    "Convert char, int and str to str"
+def oostring(obj, base):
+    """
+    Convert char, int, float, instances and str to str.
+    
+    Base is used only for formatting int: for other types is ignored
+    and should be set to -1. For int only base 8, 10 and 16 are
+    supported.
+    """
+    if isinstance(obj, int):
+        assert base in (-1, 8, 10, 16)
+        fmt = {-1:'%d', 8:'%o', 10:'%d', 16:'%x'}[base]
+        obj = fmt % obj
+    elif isinstance(obj, _view):
+        obj = '<%s object>' % obj._inst._TYPE._name
     return make_string(str(obj))
 
 def setItemType(LIST, ITEMTYPE):

Modified: pypy/dist/pypy/rpython/ootypesystem/rbuiltin.py
==============================================================================
--- pypy/dist/pypy/rpython/ootypesystem/rbuiltin.py	(original)
+++ pypy/dist/pypy/rpython/ootypesystem/rbuiltin.py	Tue May 16 14:12:17 2006
@@ -60,7 +60,9 @@
 def rtype_oostring(hop):
     assert isinstance(hop.args_s[0],(annmodel.SomeInteger,
                                      annmodel.SomeChar,
-                                     annmodel.SomeString))
+                                     annmodel.SomeString,
+                                     annmodel.SomeOOInstance))
+    assert isinstance(hop.args_s[1], annmodel.SomeInteger)
     return hop.genop('oostring', hop.args_v, resulttype = ootype.String)
 
 

Modified: pypy/dist/pypy/rpython/ootypesystem/rclass.py
==============================================================================
--- pypy/dist/pypy/rpython/ootypesystem/rclass.py	(original)
+++ pypy/dist/pypy/rpython/ootypesystem/rclass.py	Tue May 16 14:12:17 2006
@@ -379,6 +379,13 @@
         vinst, = hop.inputargs(self)
         return hop.genop('oononnull', [vinst], resulttype=ootype.Bool)
 
+    def ll_const(c):
+        return c
+    ll_const = staticmethod(ll_const)
+
+    def ll_str(self, instance):
+        return ootype.oostring(instance, self.ll_const(-1))
+
     def rtype_type(self, hop):
         vinst, = hop.inputargs(self)
         if hop.args_s[0].can_be_none():

Modified: pypy/dist/pypy/rpython/ootypesystem/rlist.py
==============================================================================
--- pypy/dist/pypy/rpython/ootypesystem/rlist.py	(original)
+++ pypy/dist/pypy/rpython/ootypesystem/rlist.py	Tue May 16 14:12:17 2006
@@ -39,7 +39,6 @@
         result = self.LIST.ll_newlist(n)
         return result
 
-
     def send_message(self, hop, message, can_raise=False, v_args=None):
         if v_args is None:
             v_args = hop.inputargs(self, *hop.args_r[1:])

Modified: pypy/dist/pypy/rpython/ootypesystem/rstr.py
==============================================================================
--- pypy/dist/pypy/rpython/ootypesystem/rstr.py	(original)
+++ pypy/dist/pypy/rpython/ootypesystem/rstr.py	Tue May 16 14:12:17 2006
@@ -2,6 +2,7 @@
 from pypy.rpython.rstr import AbstractStringRepr,AbstractCharRepr,\
      AbstractUniCharRepr, AbstractStringIteratorRepr,\
      AbstractLLHelpers
+from pypy.rpython.rmodel import IntegerRepr
 from pypy.rpython.lltypesystem.lltype import Ptr, Char, UniChar
 from pypy.rpython.ootypesystem import ootype
 
@@ -60,8 +61,11 @@
 
 class LLHelpers(AbstractLLHelpers):
 
+    def ll_const(c):
+        return c
+
     def ll_chr2str(ch):
-        return ootype.oostring(ch)
+        return ootype.oostring(ch, LLHelpers.ll_const(-1))
 
     def ll_char_mul(ch, times):
         buf = ootype.new(ootype.StringBuilder)
@@ -143,6 +147,59 @@
     def ll_stringslice_minusone(s):
         return s.ll_substring(0, s.ll_strlen()-1)
 
+    def do_stringformat(cls, hop, sourcevarsrepr):
+        InstanceRepr = hop.rtyper.type_system.rclass.InstanceRepr
+        string_repr = hop.rtyper.type_system.rstr.string_repr
+        s_str = hop.args_s[0]
+        assert s_str.is_constant()
+        s = s_str.const
+
+        c_append = hop.inputconst(ootype.Void, 'll_append')
+        c_build = hop.inputconst(ootype.Void, 'll_build')
+        cm1 = hop.inputconst(ootype.Signed, -1)
+        c8 = hop.inputconst(ootype.Signed, 8)
+        c10 = hop.inputconst(ootype.Signed, 10)
+        c16 = hop.inputconst(ootype.Signed, 16)
+        c_StringBuilder = hop.inputconst(ootype.Void, ootype.StringBuilder)        
+        v_buf = hop.genop("new", [c_StringBuilder], resulttype=ootype.StringBuilder)
+
+        things = cls.parse_fmt_string(s)
+        argsiter = iter(sourcevarsrepr)
+        for thing in things:
+            if isinstance(thing, tuple):
+                code = thing[0]
+                vitem, r_arg = argsiter.next()
+                if not hasattr(r_arg, 'll_str'):
+                    raise TyperError("ll_str unsupported for: %r" % r_arg)
+                if code == 's':
+                    # TODO: for now it works only with types supported by oostring
+                    vchunk = hop.genop('oostring', [vitem, cm1], resulttype=ootype.String)
+                elif code == 'd':
+                    assert isinstance(r_arg, IntegerRepr)
+                    vchunk = hop.genop('oostring', [vitem, c10], resulttype=ootype.String)
+                elif code == 'f':
+                    #assert isinstance(r_arg, FloatRepr)
+                    vchunk = hop.gendirectcall(r_arg.ll_str, vitem)
+                elif code == 'x':
+                    assert isinstance(r_arg, IntegerRepr)
+                    vchunk = hop.genop('oostring', [vitem, c16], resulttype=ootype.String)
+                elif code == 'o':
+                    assert isinstance(r_arg, IntegerRepr)
+                    vchunk = hop.genop('oostring', [vitem, c8], resulttype=ootype.String)
+                elif code == 'r' and isinstance(r_arg, InstanceRepr):
+                    vchunk = hop.gendirectcall(r_arg.ll_str, vitem)
+                else:
+                    raise TyperError, "%%%s is not RPython" % (code, )
+            else:
+                vchunk = hop.inputconst(string_repr, thing)
+            #i = inputconst(Signed, i)
+            #hop.genop('setarrayitem', [vtemp, i, vchunk])
+            hop.genop('oosend', [c_append, v_buf, vchunk], resulttype=ootype.Void)
+
+        hop.exception_cannot_occur()   # to ignore the ZeroDivisionError of '%'
+        return hop.genop('oosend', [c_build, v_buf], resulttype=ootype.String)        
+    do_stringformat = classmethod(do_stringformat)
+
 def add_helpers():
     dic = {}
     for name, meth in ootype.String._GENERIC_METHODS.iteritems():
@@ -192,3 +249,16 @@
 
 string_iterator_repr = StringIteratorRepr()
 
+
+# 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>")
+
+unboxed_instance_str_prefix = string_repr.convert_const("")
+
+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/rstr.py
==============================================================================
--- pypy/dist/pypy/rpython/rstr.py	(original)
+++ pypy/dist/pypy/rpython/rstr.py	Tue May 16 14:12:17 2006
@@ -298,10 +298,15 @@
         r_tuple = hop.args_r[1]
         v_tuple = hop.args_v[1]
 
+        if hop.rtyper.type_system.name == 'ootypesystem':
+            getfield = 'oogetfield'
+        else:
+            getfield = 'getfiel'
+
         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],
+            vitem = hop.genop(getfield, [v_tuple, cname],
                               resulttype=r_arg)
             sourcevars.append((vitem, r_arg))
 
@@ -545,3 +550,28 @@
             raise IndexError
         return cls.ll_stritem_nonneg(s, i)
     ll_stritem_checked = classmethod(ll_stritem_checked)
+
+    def parse_fmt_string(fmt):
+        # we support x, d, s, f, [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 = ''
+                if f not in 'xdosrf':
+                    raise TyperError("Unsupported formatting specifier: %r in %r" % (f, fmt))
+
+                r.append((f,))
+            else:
+                curstr += c
+        if curstr:
+            r.append(curstr)
+        return r

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 May 16 14:12:17 2006
@@ -1,5 +1,6 @@
 import random
 from pypy.rpython.lltypesystem.lltype import *
+from pypy.rpython.rstr import AbstractLLHelpers
 from pypy.rpython.lltypesystem.rstr import LLHelpers, STR
 from pypy.rpython.rtyper import RPythonTyper, TyperError
 from pypy.rpython.test.test_llinterp import interpret, interpret_raises
@@ -22,6 +23,11 @@
         res = LLHelpers.ll_rfind(llstr(s1), llstr(s2), 0, n1)
         assert res == s1.rfind(s2)
 
+def test_parse_fmt():
+    assert AbstractLLHelpers.parse_fmt_string('a') == ['a']
+    assert AbstractLLHelpers.parse_fmt_string('%s') == [('s',)]
+    assert AbstractLLHelpers.parse_fmt_string("name '%s' is not defined") == ["name '", ("s",), "' is not defined"]
+
 
 class AbstractTestRstr:
 
@@ -376,100 +382,99 @@
         assert self.ll_to_string(res) == 'hell'
 
 
-def test_parse_fmt():
-    assert LLHelpers.parse_fmt_string('a') == ['a']
-    assert LLHelpers.parse_fmt_string('%s') == [('s',)]
-    assert LLHelpers.parse_fmt_string("name '%s' is not defined") == ["name '", ("s",), "' is not defined"]
-
-def test_strformat():
-    def percentS(s):
-        return "before %s after" % (s,)
+    def test_strformat(self):
+        def percentS(s):
+            return "before %s after" % (s,)
 
-    res = interpret(percentS, ['1'])
-    assert ''.join(res.chars) == 'before 1 after'
+        res = self.interpret(percentS, ['1'])
+        assert self.ll_to_string(res) == 'before 1 after'
 
-    def percentD(i):
-        return "bing %d bang" % (i,)
-    
-    res = interpret(percentD, [23])
-    assert ''.join(res.chars) == 'bing 23 bang'
+        def percentD(i):
+            return "bing %d bang" % (i,)
 
-    def percentX(i):
-        return "bing %x bang" % (i,)
+        res = self.interpret(percentD, [23])
+        assert self.ll_to_string(res) == 'bing 23 bang'
 
-    res = interpret(percentX, [23])
-    assert ''.join(res.chars) == 'bing 17 bang'
+        def percentX(i):
+            return "bing %x bang" % (i,)
 
-    res = interpret(percentX, [-123])
-    assert ''.join(res.chars) == 'bing -7b bang'
+        res = self.interpret(percentX, [23])
+        assert self.ll_to_string(res) == 'bing 17 bang'
 
-    def percentO(i):
-        return "bing %o bang" % (i,)
-    
-    res = interpret(percentO, [23])
-    assert ''.join(res.chars) == 'bing 27 bang'
+        res = self.interpret(percentX, [-123])
+        assert self.ll_to_string(res) == 'bing -7b bang'
 
-    res = interpret(percentO, [-123])
-    assert ''.join(res.chars) == 'bing -173 bang'
+        def percentO(i):
+            return "bing %o bang" % (i,)
 
-    def moreThanOne(s, d, x, o):
-        return "string: %s decimal: %d hex: %x oct: %o" % (s, d, x, o)
+        res = self.interpret(percentO, [23])
+        assert self.ll_to_string(res) == 'bing 27 bang'
 
-    args = 'a', 2, 3, 4
-    res = interpret(moreThanOne, list(args))
-    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'
-
-def test_strformat_instance():
-    class C:
-        pass
-    class D(C):
-        pass
-    def dummy(i):
-        if i:
-            x = C()
-        else:
-            x = D()
-        return str(x)
-        
-    res = interpret(dummy, [1])
-    assert ''.join(res.chars) == ''
+        res = self.interpret(percentO, [-123])
+        assert self.ll_to_string(res) == 'bing -173 bang'
 
-    res = interpret(dummy, [0])
-    assert ''.join(res.chars) == ''
+        def moreThanOne(s, d, x, o):
+            return "string: %s decimal: %d hex: %x oct: %o" % (s, d, x, o)
 
-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)
-        
-    res = interpret(dummy, [1])
-    assert ''.join(res.chars) == 'what a nice , much nicer than '
+        args = 'a', 2, 3, 4
+        res = self.interpret(moreThanOne, list(args))
+        assert self.ll_to_string(res) == moreThanOne(*args)
+
+    def test_strformat_nontuple(self):
+        def percentD(i):
+            return "before %d after" % i
+
+        res = self.interpret(percentD, [1])
+        assert self.ll_to_string(res) == 'before 1 after'
+
+        def percentS(i):
+            return "before %s after" % i
 
-    res = interpret(dummy, [0])
-    assert ''.join(res.chars) == 'what a nice , much nicer than '
+        res = self.interpret(percentS, ['D'])
+        assert self.ll_to_string(res) == 'before D after'
+
+    def test_strformat_instance(self):
+        class C:
+            pass
+        class D(C):
+            pass
+        def dummy(i):
+            if i:
+                x = C()
+            else:
+                x = D()
+            return str(x)
+
+        res = self.ll_to_string(self.interpret(dummy, [1]))
+        assert res.startswith('<')
+        assert res.endswith('C object>')
+
+        res = self.ll_to_string(self.interpret(dummy, [0]))
+        assert res.startswith('<')
+        assert res.endswith('D object>')
+
+    def test_percentformat_instance(self):
+        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)
+
+        res = self.ll_to_string(self.interpret(dummy, [1]))
+        res = res.replace('pypy.rpython.test.test_rstr.', '')
+        assert res == 'what a nice , much nicer than '
+
+        res = self.ll_to_string(self.interpret(dummy, [0]))
+        res = res.replace('pypy.rpython.test.test_rstr.', '')        
+        assert res == 'what a nice , much nicer than '
 
 def test_split():
     def fn(i):


From antocuni at codespeak.net  Tue May 16 14:34:03 2006
From: antocuni at codespeak.net (antocuni at codespeak.net)
Date: Tue, 16 May 2006 14:34:03 +0200 (CEST)
Subject: [pypy-svn] r27272 - in pypy/dist/pypy/rpython: . ootypesystem test
Message-ID: <20060516123403.E0B3C10070@code0.codespeak.net>

Author: antocuni
Date: Tue May 16 14:33:55 2006
New Revision: 27272

Modified:
   pypy/dist/pypy/rpython/ootypesystem/ootype.py
   pypy/dist/pypy/rpython/ootypesystem/rstr.py
   pypy/dist/pypy/rpython/rstr.py
   pypy/dist/pypy/rpython/test/test_rstr.py
Log:
Added support for split, replace and contains to ootypesystem strings.


Modified: pypy/dist/pypy/rpython/ootypesystem/ootype.py
==============================================================================
--- pypy/dist/pypy/rpython/ootypesystem/ootype.py	(original)
+++ pypy/dist/pypy/rpython/ootypesystem/ootype.py	Tue May 16 14:33:55 2006
@@ -290,6 +290,9 @@
             "ll_upper": Meth([], self.SELFTYPE_T),
             "ll_lower": Meth([], self.SELFTYPE_T),
             "ll_substring": Meth([Signed, Signed], self.SELFTYPE_T), # ll_substring(start, count)
+            "ll_split_chr": Meth([Char], List(self.SELFTYPE_T)),
+            "ll_contains": Meth([Char], Bool),
+            "ll_replace_chr_chr": Meth([Char, Char], self.SELFTYPE_T),
             })
         self._setup_methods(generic_types)
 
@@ -872,6 +875,20 @@
         # NOT_RPYTHON
         return make_string(self._str[start:start+count])
 
+    def ll_split_chr(self, ch):
+        # NOT_RPYTHON
+        res = _list(List(String))
+        res._list = [make_string(s) for s in self._str.split(ch)]
+        return res
+
+    def ll_contains(self, ch):
+        # NOT_RPYTHON
+        return ch in self._str
+
+    def ll_replace_chr_chr(self, ch1, ch2):
+        # NOT_RPYTHON
+        return make_string(self._str.replace(ch1, ch2))
+
 class _null_string(_null_mixin(_string), _string):
     def __init__(self, STRING):
         self.__dict__["_TYPE"] = STRING

Modified: pypy/dist/pypy/rpython/ootypesystem/rstr.py
==============================================================================
--- pypy/dist/pypy/rpython/ootypesystem/rstr.py	(original)
+++ pypy/dist/pypy/rpython/ootypesystem/rstr.py	Tue May 16 14:33:55 2006
@@ -147,6 +147,9 @@
     def ll_stringslice_minusone(s):
         return s.ll_substring(0, s.ll_strlen()-1)
 
+    def ll_split_chr(LIST, s, c):
+        return s.ll_split_chr(c)
+
     def do_stringformat(cls, hop, sourcevarsrepr):
         InstanceRepr = hop.rtyper.type_system.rclass.InstanceRepr
         string_repr = hop.rtyper.type_system.rstr.string_repr

Modified: pypy/dist/pypy/rpython/rstr.py
==============================================================================
--- pypy/dist/pypy/rpython/rstr.py	(original)
+++ pypy/dist/pypy/rpython/rstr.py	Tue May 16 14:33:55 2006
@@ -170,7 +170,11 @@
     def rtype_method_split(self, hop):
         rstr = hop.rtyper.type_system.rstr
         v_str, v_chr = hop.inputargs(rstr.string_repr, rstr.char_repr)
-        cLIST = hop.inputconst(Void, hop.r_result.lowleveltype.TO)
+        try:
+            list_type = hop.r_result.lowleveltype.TO
+        except AttributeError:
+            list_type = hop.r_result.lowleveltype
+        cLIST = hop.inputconst(Void, list_type)
         hop.exception_cannot_occur()
         return hop.gendirectcall(self.ll.ll_split_chr, cLIST, v_str, v_chr)
 

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 May 16 14:33:55 2006
@@ -476,48 +476,48 @@
         res = res.replace('pypy.rpython.test.test_rstr.', '')        
         assert res == '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)
+    def test_split(self):
+        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 = self.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])#, 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
-    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, ())
+    def test_contains(self):
+        def fn(i):
+            s = 'Hello world'
+            return chr(i) in s
+        for i in range(256):
+            res = self.interpret(fn, [i])#, view=i==42)
+            assert res == fn(i)
+
+    def test_replace(self):
+        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 = self.interpret(fn, ['a', 'c'])
+        assert res == 4
+        res = self.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, ())
 
 def test_int():
     s1 = [ '42', '01001', 'abc', 'ABC', '4aBc', ' 12ef ', '+42', 'foo', '42foo', '42.1', '']


From pedronis at codespeak.net  Tue May 16 18:16:06 2006
From: pedronis at codespeak.net (pedronis at codespeak.net)
Date: Tue, 16 May 2006 18:16:06 +0200 (CEST)
Subject: [pypy-svn] r27277 - in pypy/dist/pypy/rpython: . test
Message-ID: <20060516161606.397C01007E@code0.codespeak.net>

Author: pedronis
Date: Tue May 16 18:16:04 2006
New Revision: 27277

Modified:
   pypy/dist/pypy/rpython/rstr.py
   pypy/dist/pypy/rpython/test/test_rstr.py
Log:
lltype str tests were ignored (?)

fix typo



Modified: pypy/dist/pypy/rpython/rstr.py
==============================================================================
--- pypy/dist/pypy/rpython/rstr.py	(original)
+++ pypy/dist/pypy/rpython/rstr.py	Tue May 16 18:16:04 2006
@@ -305,7 +305,7 @@
         if hop.rtyper.type_system.name == 'ootypesystem':
             getfield = 'oogetfield'
         else:
-            getfield = 'getfiel'
+            getfield = 'getfield'
 
         sourcevars = []
         for fname, r_arg in zip(r_tuple.fieldnames, r_tuple.items_r):

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 May 16 18:16:04 2006
@@ -580,7 +580,7 @@
     res = interpret(g, [-2])
     assert res._obj.value == 42
 
-class xTestLltype(AbstractTestRstr):
+class TestLltype(AbstractTestRstr):
     ts = "lltype"
 
     def ll_to_string(self, s):


From pedronis at codespeak.net  Tue May 16 19:33:20 2006
From: pedronis at codespeak.net (pedronis at codespeak.net)
Date: Tue, 16 May 2006 19:33:20 +0200 (CEST)
Subject: [pypy-svn] r27293 - in pypy/dist/pypy/rpython/lltypesystem: . test
Message-ID: <20060516173320.42A9F10080@code0.codespeak.net>

Author: pedronis
Date: Tue May 16 19:33:18 2006
New Revision: 27293

Modified:
   pypy/dist/pypy/rpython/lltypesystem/llmemory.py
   pypy/dist/pypy/rpython/lltypesystem/lltype.py
   pypy/dist/pypy/rpython/lltypesystem/test/test_llmemory.py
   pypy/dist/pypy/rpython/lltypesystem/test/test_lltype.py
Log:
don't crash on repr/str of dead pointer/address

some support for generating exceptions out of accesses to raw_freed stuff



Modified: pypy/dist/pypy/rpython/lltypesystem/llmemory.py
==============================================================================
--- pypy/dist/pypy/rpython/lltypesystem/llmemory.py	(original)
+++ pypy/dist/pypy/rpython/lltypesystem/llmemory.py	Tue May 16 19:33:18 2006
@@ -508,7 +508,8 @@
     return size.raw_malloc([])
 
 def raw_free(adr):
-    pass   # for now
+    assert isinstance(adr.ob._obj, lltype._parentable)
+    adr.ob._obj._free()
 
 def raw_malloc_usage(size):
     if isinstance(size, AddressOffset):

Modified: pypy/dist/pypy/rpython/lltypesystem/lltype.py
==============================================================================
--- pypy/dist/pypy/rpython/lltypesystem/lltype.py	(original)
+++ pypy/dist/pypy/rpython/lltypesystem/lltype.py	Tue May 16 19:33:18 2006
@@ -875,12 +875,14 @@
         
     def _getobj(self):
         obj = self._obj0
-        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()
+        if obj is not None:
+            if self._weak:
+                obj = obj()
+                if obj is None:
+                    raise RuntimeError("accessing already garbage collected %r"
+                                   % (self._T,))
+            if not isinstance(obj, int):
+                obj._check()
         return obj
     _obj = property(_getobj)
 
@@ -977,7 +979,10 @@
         return '<%s>' % (self,)
 
     def __str__(self):
-        return '* %s' % (self._obj, )
+        try:
+            return '* %s' % (self._obj, )
+        except RuntimeError:
+            return '* DEAD %s' % self._T
 
     def __call__(self, *args):
         if isinstance(self._T, FuncType):
@@ -1057,11 +1062,16 @@
     __slots__ = ('_TYPE',
                  '_parent_type', '_parent_index', '_keepparent',
                  '_wrparent',
-                 '__weakref__')
+                 '__weakref__',
+                 '_dead')
 
     def __init__(self, TYPE):
         self._wrparent = None
         self._TYPE = TYPE
+        self._dead = False
+
+    def _free(self):
+        self._dead = True
 
     def _setparentstructure(self, parent, parentindex):
         self._wrparent = pickleable_weakref(parent)
@@ -1085,6 +1095,8 @@
         return None
 
     def _check(self):
+        if self._dead:
+            raise RuntimeError("accessing freed %r" % self._TYPE)
         self._parentstructure()
 
     __getstate__ = getstate_with_slots

Modified: pypy/dist/pypy/rpython/lltypesystem/test/test_llmemory.py
==============================================================================
--- pypy/dist/pypy/rpython/lltypesystem/test/test_llmemory.py	(original)
+++ pypy/dist/pypy/rpython/lltypesystem/test/test_llmemory.py	Tue May 16 19:33:18 2006
@@ -295,6 +295,49 @@
     py.test.raises(IndexError,
                    "(adr + offsetof(S, 'y') + itemoffsetof(A, 10)).signed[0]")
 
+def test_raw_free():
+    A = lltype.GcArray(lltype.Signed)
+    adr = raw_malloc(sizeof(A, 10))
+    p_a = cast_adr_to_ptr(adr, lltype.Ptr(A))
+    p_a[0] = 1
+    raw_free(adr)
+    py.test.raises(RuntimeError, "p_a[0]")
+    py.test.raises(RuntimeError, "p_a[0] = 2")
+    repr(adr)
+    str(p_a)
+
+    S = lltype.GcStruct('S', ('x', lltype.Signed))
+    adr = raw_malloc(sizeof(S))
+    p_s = cast_adr_to_ptr(adr, lltype.Ptr(S))
+    p_s.x = 1
+    raw_free(adr)
+    py.test.raises(RuntimeError, "p_s.x")
+    py.test.raises(RuntimeError, "p_s.x = 2")
+    repr(adr)
+    str(p_s)
+    
+    T = lltype.GcStruct('T', ('s', S))
+    adr = raw_malloc(sizeof(T))
+    p_s = cast_adr_to_ptr(adr, lltype.Ptr(S))
+    p_s.x = 1
+    raw_free(adr)
+    py.test.raises(RuntimeError, "p_s.x")
+    py.test.raises(RuntimeError, "p_s.x = 2")
+    repr(adr)
+    str(p_s)
+    
+    U = lltype.Struct('U', ('y', lltype.Signed))
+    T = lltype.GcStruct('T', ('x', lltype.Signed), ('u', U))
+    adr = raw_malloc(sizeof(T))
+    p_t = cast_adr_to_ptr(adr, lltype.Ptr(T))
+    p_u = p_t.u
+    p_u.y = 1
+    raw_free(adr)
+    py.test.raises(RuntimeError, "p_u.y")
+    py.test.raises(RuntimeError, "p_u.y = 2")
+    repr(adr)
+    str(p_u)
+    
 def test_inlined_substruct():
     T = lltype.Struct('T', ('x', lltype.Signed))
     S1 = lltype.GcStruct('S1', ('t1', T), ('t2', T))

Modified: pypy/dist/pypy/rpython/lltypesystem/test/test_lltype.py
==============================================================================
--- pypy/dist/pypy/rpython/lltypesystem/test/test_lltype.py	(original)
+++ pypy/dist/pypy/rpython/lltypesystem/test/test_lltype.py	Tue May 16 19:33:18 2006
@@ -670,3 +670,13 @@
     assert typeOf(t) == Ptr(T)
     assert cast_ptr_to_int(t) == 21
     assert s == cast_pointer(Ptr(S), t)
+
+def test_str_of_dead_ptr():
+    S = Struct('S', ('x', Signed))
+    T = GcStruct('T', ('s', S))
+    t = malloc(T)
+    s = t.s
+    del t
+    import gc
+    gc.collect()
+    repr(s)


From arigo at codespeak.net  Tue May 16 20:50:15 2006
From: arigo at codespeak.net (arigo at codespeak.net)
Date: Tue, 16 May 2006 20:50:15 +0200 (CEST)
Subject: [pypy-svn] r27296 - in pypy/dist/pypy: rpython/lltypesystem
	rpython/memory rpython/memory/test translator/c/test
	translator/stackless
Message-ID: <20060516185015.06B8E10080@code0.codespeak.net>

Author: arigo
Date: Tue May 16 20:50:13 2006
New Revision: 27296

Modified:
   pypy/dist/pypy/rpython/lltypesystem/llmemory.py
   pypy/dist/pypy/rpython/memory/gc.py
   pypy/dist/pypy/rpython/memory/gctransform.py
   pypy/dist/pypy/rpython/memory/test/test_transformed_gc.py
   pypy/dist/pypy/translator/c/test/test_newgc.py
   pypy/dist/pypy/translator/stackless/frame.py
Log:
Stackless GC tests now passing!  Both on llinterp and in translated C.

* introduced a generic GCREF opaque pointer type for things like
    the return value of the malloc() functions

* display more information during a collect



Modified: pypy/dist/pypy/rpython/lltypesystem/llmemory.py
==============================================================================
--- pypy/dist/pypy/rpython/lltypesystem/llmemory.py	(original)
+++ pypy/dist/pypy/rpython/lltypesystem/llmemory.py	Tue May 16 20:50:13 2006
@@ -385,6 +385,9 @@
 NULL.intaddress = 0      # this is to make memory.lladdress more happy
 Address = lltype.Primitive("Address", NULL)
 
+# GCREF is similar to Address but it is GC-aware
+GCREF = lltype.Ptr(lltype.GcOpaqueType('GCREF'))
+
 
 class _fakeaccessor(object):
     def __init__(self, addr):

Modified: pypy/dist/pypy/rpython/memory/gc.py
==============================================================================
--- pypy/dist/pypy/rpython/memory/gc.py	(original)
+++ pypy/dist/pypy/rpython/memory/gc.py	Tue May 16 20:50:13 2006
@@ -112,8 +112,9 @@
     _size_gc_header = GCHeaderOffset(HDR)
 
     def __init__(self, AddressLinkedList, start_heap_size=4096, get_roots=None):
-        self.bytes_malloced = 0
-        self.heap_size = start_heap_size
+        self.heap_usage = 0          # at the end of the latest collection
+        self.bytes_malloced = 0      # since the latest collection
+        self.bytes_malloced_threshold = start_heap_size
         #need to maintain a list of malloced objects, since we used the systems
         #allocator and can't walk the heap
         self.malloced_objects = None
@@ -125,18 +126,20 @@
         self.malloced_objects = self.AddressLinkedList()
 
     def malloc(self, typeid, length=0):
-        if self.bytes_malloced > self.heap_size:
-            self.collect()
         size = self.fixed_size(typeid)
         if self.is_varsize(typeid):
             itemsize = self.varsize_item_sizes(typeid)
             offset_to_length = self.varsize_offset_to_length(typeid)
-            return self.malloc_varsize(typeid, length, size, itemsize,
-                                       offset_to_length, True)
-        return self.malloc_fixedsize(typeid, size, True)
+            ref = self.malloc_varsize(typeid, length, size, itemsize,
+                                      offset_to_length, True)
+        else:
+            ref = self.malloc_fixedsize(typeid, size, True)
+        # XXX lots of cast and reverse-cast around, but this malloc()
+        # should eventually be killed
+        return lltype.cast_ptr_to_adr(ref)
 
     def malloc_fixedsize(self, typeid, size, can_collect):
-        if can_collect and self.bytes_malloced > self.heap_size:
+        if can_collect and self.bytes_malloced > self.bytes_malloced_threshold:
             self.collect()
         size_gc_header = MarkSweepGC._size_gc_header
         result = raw_malloc(size_gc_header + size)
@@ -144,11 +147,12 @@
         hdr.typeid = typeid << 1
         self.malloced_objects.append(result)
         self.bytes_malloced += raw_malloc_usage(size + size_gc_header)
-        return result + size_gc_header
+        result += size_gc_header
+        return llmemory.cast_adr_to_ptr(result, llmemory.GCREF)
 
     def malloc_varsize(self, typeid, length, size, itemsize, offset_to_length,
                        can_collect):
-        if can_collect and self.bytes_malloced > self.heap_size:
+        if can_collect and self.bytes_malloced > self.bytes_malloced_threshold:
             self.collect()
         try:
             varsize = rarithmetic.ovfcheck(itemsize * length)
@@ -163,13 +167,12 @@
         hdr.typeid = typeid << 1
         self.malloced_objects.append(result)
         self.bytes_malloced += raw_malloc_usage(size + size_gc_header)
-        return result + size_gc_header
+        result += size_gc_header
+        return llmemory.cast_adr_to_ptr(result, llmemory.GCREF)
 
     def collect(self):
         import os
-        os.write(2, 'collecting... ')
-        old_malloced = self.bytes_malloced
-        self.bytes_malloced = 0
+        os.write(2, 'collecting...\n')
         roots = self.get_roots()
         objects = self.AddressLinkedList()
         while 1:
@@ -184,6 +187,9 @@
 ##            gc_info = curr.address[0] - MarkSweepGC._size_gc_header
 ##            gc_info.signed[0] = gc_info.signed[0] & (~1)
         free_non_gc_object(roots)
+        # from this point onwards, no more mallocs should be possible
+        old_malloced = self.bytes_malloced
+        self.bytes_malloced = 0
         while 1:  #mark
             curr = objects.pop()
 ##             print "object: ", curr
@@ -240,17 +246,25 @@
                 raw_free(curr)
         free_non_gc_object(self.malloced_objects)
         self.malloced_objects = newmo
-        if curr_heap_size > self.heap_size:
-            self.heap_size = curr_heap_size
+        if curr_heap_size > self.bytes_malloced_threshold:
+            self.bytes_malloced_threshold = curr_heap_size
         # warning, the following debug print allocates memory to manipulate
         # the strings!  so it must be at the end
-        os.write(2, "malloced before this collection %s bytes. " % old_malloced)
-        os.write(2, "freed %s bytes. the heap is now %s bytes.\n" % (freed_size, curr_heap_size))
+        os.write(2, "  malloced since previous collection: %s bytes\n" %
+                 old_malloced)
+        os.write(2, "  heap usage at start of collection:  %s bytes\n" %
+                 (self.heap_usage + old_malloced))
+        os.write(2, "  freed:                              %s bytes\n" %
+                 freed_size)
+        os.write(2, "  new heap usage:                     %s bytes\n" %
+                 curr_heap_size)
+        assert self.heap_usage + old_malloced == curr_heap_size + freed_size
+        self.heap_usage = curr_heap_size
 
     STATISTICS_NUMBERS = 2
 
     def statistics(self):
-        return self.heap_size, self.bytes_malloced
+        return self.heap_usage, self.bytes_malloced
 
     def size_gc_header(self, typeid=0):
         return MarkSweepGC._size_gc_header

Modified: pypy/dist/pypy/rpython/memory/gctransform.py
==============================================================================
--- pypy/dist/pypy/rpython/memory/gctransform.py	(original)
+++ pypy/dist/pypy/rpython/memory/gctransform.py	Tue May 16 20:50:13 2006
@@ -859,16 +859,17 @@
 
         classdef = bk.getuniqueclassdef(GCClass)
         s_gcdata = annmodel.SomeInstance(classdef)
+        s_gcref = annmodel.SomePtr(llmemory.GCREF)
         self.malloc_fixedsize_ptr = getfn(
             GCClass.malloc_fixedsize.im_func,
             [s_gcdata, annmodel.SomeInteger(nonneg=True),
              annmodel.SomeInteger(nonneg=True),
-             annmodel.SomeBool()], annmodel.SomeAddress(),
+             annmodel.SomeBool()], s_gcref,
             inline = True)
         self.malloc_varsize_ptr = getfn(
             GCClass.malloc_varsize.im_func,
             [s_gcdata] + [annmodel.SomeInteger(nonneg=True) for i in range(5)]
-            + [annmodel.SomeBool()], annmodel.SomeAddress())
+            + [annmodel.SomeBool()], s_gcref)
         self.collect_ptr = getfn(GCClass.collect.im_func,
             [s_gcdata], annmodel.s_None)
 
@@ -1110,7 +1111,6 @@
         assert PTRTYPE.TO == TYPE
         type_id = self.get_type_id(TYPE)
 
-        v = varoftype(llmemory.Address)
         c_type_id = rmodel.inputconst(lltype.Signed, type_id)
         info = self.type_info_list[type_id]
         c_size = rmodel.inputconst(lltype.Signed, info["fixedsize"])
@@ -1124,10 +1124,11 @@
             args = [self.malloc_varsize_ptr, self.c_const_gc, c_type_id,
                     v_length, c_size, c_varitemsize, c_ofstolength,
                     c_can_collect]
+        v = varoftype(llmemory.GCREF)
         newop = SpaceOperation("direct_call", args, v)
         ops, index = self.protect_roots(newop, livevars, block,
                                         block.operations.index(op))
-        ops.append(SpaceOperation("cast_adr_to_ptr", [v], op.result))
+        ops.append(SpaceOperation("cast_opaque_ptr", [v], op.result))
         return ops
 
     replace_malloc_varsize = replace_malloc

Modified: pypy/dist/pypy/rpython/memory/test/test_transformed_gc.py
==============================================================================
--- pypy/dist/pypy/rpython/memory/test/test_transformed_gc.py	(original)
+++ pypy/dist/pypy/rpython/memory/test/test_transformed_gc.py	Tue May 16 20:50:13 2006
@@ -155,8 +155,11 @@
 ##         gclltype.use_gc = cls.old
 
 from pypy.translator.c import gc
+from pypy.annotation import model as annmodel
+from pypy.rpython.lltypesystem import lltype
 from pypy.rpython.memory import gctransform
 from pypy.rpython.memory.support import INT_SIZE
+from pypy import conftest
 
 
 def rtype(func, inputtypes, specialize=True):
@@ -165,33 +168,38 @@
     t.buildannotator().build_types(func, inputtypes)
     if specialize:
         t.buildrtyper().specialize(t)
+    if conftest.option.view:
+        t.view()
     return t
 
 class GCTest(object):
     gcpolicy = None
 
-    def runner(self, f, withargs=False, statistics=False):
-        if withargs:
-            def entrypoint(argv):
-                x = int(argv[0])
-                y = int(argv[1])
+    def runner(self, f, nbargs=0, statistics=False):
+        if nbargs == 2:
+            def entrypoint(args):
+                x = args[0]
+                y = args[1]
                 r = f(x, y)
                 return r
-        else:
-            def entrypoint(argv):
+        elif nbargs == 0:
+            def entrypoint(args):
                 return f()
-            
+        else:
+            raise NotImplementedError("pure laziness")
+
         from pypy.rpython.llinterp import LLInterpreter
         from pypy.translator.c.genc import CStandaloneBuilder
-        from pypy.annotation.listdef import s_list_of_strings
 
-        t = rtype(entrypoint, [s_list_of_strings])
+        ARGS = lltype.FixedSizeArray(lltype.Signed, nbargs)
+        s_args = annmodel.SomePtr(lltype.Ptr(ARGS))
+        t = rtype(entrypoint, [s_args])
         cbuild = CStandaloneBuilder(t, entrypoint, self.gcpolicy)
         db = cbuild.generate_graphs_for_llinterp()
         entrypointptr = cbuild.getentrypointptr()
         entrygraph = entrypointptr._obj.graph
-
-        r_list_of_strings = t.rtyper.getrepr(s_list_of_strings)
+        if conftest.option.view:
+            t.view()
 
         llinterp = LLInterpreter(t.rtyper)
 
@@ -199,8 +207,10 @@
         setupgraph = db.gctransformer.frameworkgc_setup_ptr.value._obj.graph
         llinterp.eval_graph(setupgraph, [])
         def run(args):
-            ll_argv = r_list_of_strings.convert_const([repr(x) for x in args])
-            res = llinterp.eval_graph(entrygraph, [ll_argv])
+            ll_args = lltype.malloc(ARGS, immortal=True)
+            for i in range(nbargs):
+                ll_args[i] = args[i]
+            res = llinterp.eval_graph(entrygraph, [ll_args])
             return res
 
         if statistics:
@@ -259,7 +269,7 @@
         def append_to_list(i, j):
             box.lst.append([i] * 50)
             return box.lst[j][0]
-        run = self.runner(append_to_list, withargs=True)
+        run = self.runner(append_to_list, nbargs=2)
         res = run([0, 0])
         assert res == 0
         for i in range(1, 15):
@@ -273,15 +283,14 @@
             for i in range(j):
                 lst.append(str(i))
             return len("".join(lst))
-        res = self.runner(concat, withargs=True)([100, 0])
-        run, statistics = self.runner(concat, withargs=True, statistics=True)
+        run, statistics = self.runner(concat, nbargs=2, statistics=True)
         res = run([100, 0])
         assert res == concat(100, 0)
         heap_size = statistics().item0
         assert heap_size < 16000 * INT_SIZE / 4 # xxx
 
 
-class INPROGRESS_TestStacklessMarkSweepGC(TestMarkSweepGC):
+class TestStacklessMarkSweepGC(TestMarkSweepGC):
 
     class gcpolicy(gc.StacklessFrameworkGcPolicy):
         class transformerclass(gctransform.StacklessFrameworkGCTransformer):

Modified: pypy/dist/pypy/translator/c/test/test_newgc.py
==============================================================================
--- pypy/dist/pypy/translator/c/test/test_newgc.py	(original)
+++ pypy/dist/pypy/translator/c/test/test_newgc.py	Tue May 16 20:50:13 2006
@@ -563,14 +563,22 @@
     from pypy.translator.c.gc import StacklessFrameworkGcPolicy as gcpolicy
 
     def getcompiled(self, f):
-        py.test.skip('in-progress')
         # XXX quick hack
         from pypy.translator.c.test.test_stackless import StacklessTest
         runner = StacklessTest()
         runner.gcpolicy = self.gcpolicy
         runner.stacklessmode = True
-        res = runner.wrap_stackless_function(f)
+        try:
+            res = runner.wrap_stackless_function(f)
+        except py.process.cmdexec.Error, e:
+            if 'Fatal PyPy error: MemoryError' in e.err:
+                res = MemoryError
+            else:
+                raise
         self.t = runner.t
         def compiled():
-            return res
+            if res is MemoryError:
+                raise MemoryError
+            else:
+                return res
         return compiled

Modified: pypy/dist/pypy/translator/stackless/frame.py
==============================================================================
--- pypy/dist/pypy/translator/stackless/frame.py	(original)
+++ pypy/dist/pypy/translator/stackless/frame.py	Tue May 16 20:50:13 2006
@@ -10,7 +10,7 @@
 # ____________________________________________________________
 # generic data types
 
-SAVED_REFERENCE = lltype.Ptr(lltype.GcOpaqueType('stackless.saved_ref'))
+SAVED_REFERENCE = llmemory.GCREF
 null_saved_ref = lltype.nullptr(SAVED_REFERENCE.TO)
 
 STORAGE_TYPES = [lltype.Void, SAVED_REFERENCE, llmemory.Address,


From cfbolz at codespeak.net  Tue May 16 20:53:00 2006
From: cfbolz at codespeak.net (cfbolz at codespeak.net)
Date: Tue, 16 May 2006 20:53:00 +0200 (CEST)
Subject: [pypy-svn] r27297 - in pypy/dist/pypy/rpython/memory: . test
Message-ID: <20060516185300.783A610080@code0.codespeak.net>

Author: cfbolz
Date: Tue May 16 20:52:58 2006
New Revision: 27297

Modified:
   pypy/dist/pypy/rpython/memory/gc.py
   pypy/dist/pypy/rpython/memory/test/test_transformed_gc.py
Log:
test + fix for the problem that static roots don't have their mark bit reset
after a collection and are considered to be already visited in the next one


Modified: pypy/dist/pypy/rpython/memory/gc.py
==============================================================================
--- pypy/dist/pypy/rpython/memory/gc.py	(original)
+++ pypy/dist/pypy/rpython/memory/gc.py	Tue May 16 20:52:58 2006
@@ -182,10 +182,11 @@
                 break
             # roots is a list of addresses to addresses:
             objects.append(curr.address[0])
-##            # constants roots are not malloced and thus don't have their mark
-##            # bit reset
-##            gc_info = curr.address[0] - MarkSweepGC._size_gc_header
-##            gc_info.signed[0] = gc_info.signed[0] & (~1)
+            # the last sweep did not clear the mark bit of static roots, 
+            # since they are not in the malloced_objects list
+            gc_info = curr.address[0] - MarkSweepGC._size_gc_header
+            hdr = llmemory.cast_adr_to_ptr(gc_info, self.HDRPTR)
+            hdr.typeid = hdr.typeid & (~1)
         free_non_gc_object(roots)
         # from this point onwards, no more mallocs should be possible
         old_malloced = self.bytes_malloced

Modified: pypy/dist/pypy/rpython/memory/test/test_transformed_gc.py
==============================================================================
--- pypy/dist/pypy/rpython/memory/test/test_transformed_gc.py	(original)
+++ pypy/dist/pypy/rpython/memory/test/test_transformed_gc.py	Tue May 16 20:52:58 2006
@@ -158,6 +158,8 @@
 from pypy.annotation import model as annmodel
 from pypy.rpython.lltypesystem import lltype
 from pypy.rpython.memory import gctransform
+from pypy.rpython.lltypesystem.lloperation import llop
+from pypy.rpython.lltypesystem import lltype
 from pypy.rpython.memory.support import INT_SIZE
 from pypy import conftest
 
@@ -259,7 +261,7 @@
         run, statistics = self.runner(malloc_a_lot, statistics=True)
         run([])
         heap_size = statistics().item0
-        assert heap_size < 16000 * INT_SIZE / 4 # xxx                    
+        assert heap_size < 16000 * INT_SIZE / 4 # xxx
 
     def test_global_list(self):
         class Box:
@@ -268,11 +270,12 @@
         box = Box()
         def append_to_list(i, j):
             box.lst.append([i] * 50)
+            llop.gc__collect(lltype.Void)
             return box.lst[j][0]
         run = self.runner(append_to_list, nbargs=2)
         res = run([0, 0])
         assert res == 0
-        for i in range(1, 15):
+        for i in range(1, 5):
             res = run([i, i - 1])
             assert res == i - 1 # crashes if constants are not considered roots
             


From ericvrp at codespeak.net  Tue May 16 21:14:19 2006
From: ericvrp at codespeak.net (ericvrp at codespeak.net)
Date: Tue, 16 May 2006 21:14:19 +0200 (CEST)
Subject: [pypy-svn] r27298 - in pypy/dist/pypy: doc translator
Message-ID: <20060516191419.20C511007C@code0.codespeak.net>

Author: ericvrp
Date: Tue May 16 21:14:18 2006
New Revision: 27298

Modified:
   pypy/dist/pypy/doc/getting-started.txt
   pypy/dist/pypy/translator/interactive.py
Log:
Added javascript source display to interactive shell and
wrote some documention about this for getting-started.


Modified: pypy/dist/pypy/doc/getting-started.txt
==============================================================================
--- pypy/dist/pypy/doc/getting-started.txt	(original)
+++ pypy/dist/pypy/doc/getting-started.txt	Tue May 16 21:14:18 2006
@@ -406,6 +406,26 @@
    5
 
 
+Translating the flow graph to Javascript code
++++++++++++++++++++++++++++++++++++++++++++++
+
+The Javascript backend is still experimental but will be worked on during this
+years `Google summer of code`_. It contains some rudimentary support for
+stackless features and a good integration with PyPy's unittesting framework.
+Code can be tested with the `Spidermonkey`_ commandline javascript interpreter
+in addition to a multitude of javascript capable browsers. 
+The emphasis of the Javascript backend is to compile RPython code into
+javascript snippets that can be used in a range of browsers. The goal is
+to make it more and more capable to produce full featured web applications.
+Please see the pypy/translator/js/test directory for example unittests.
+
+Here is a simple example to try::
+
+   >>> t = Translation(snippet.my_gcd)
+   >>> a = t.annotate([int, int])
+   >>> t.rtype()
+   >>> t.source_js()
+
 A slightly larger example
 +++++++++++++++++++++++++
 
@@ -638,6 +658,8 @@
 .. _`LLVM mailing list`: http://mail.cs.uiuc.edu/mailman/listinfo/llvmdev
 .. _`LLVM installed with version 1.7`: http://llvm.org/releases
 
+.. _`Spidermonkey`: http://www.mozilla.org/js/spidermonkey/
+.. _`Google summer of code`: http://code.google.com/soc
 
 .. _Dot Graphviz:           http://www.research.att.com/sw/tools/graphviz/
 .. _Pygame:                 http://www.pygame.org/

Modified: pypy/dist/pypy/translator/interactive.py
==============================================================================
--- pypy/dist/pypy/translator/interactive.py	(original)
+++ pypy/dist/pypy/translator/interactive.py	Tue May 16 21:14:18 2006
@@ -18,6 +18,7 @@
 
    'fork_before': None,
 
+   'raisingop2direct_call' : False,
    'merge_if_blocks': True
 }
 
@@ -49,10 +50,11 @@
         'annotate': ['debug'],
         'rtype': ['insist'],
         'ootype': [],
-        'backendopt': ['merge_if_blocks'],
+        'backendopt': ['raisingop2direct_call', 'merge_if_blocks'],
         'stackcheckinsertion': [],
         'database_c': ['gc', 'stackless'],
-        'source_llvm': ['gc', 'stackless'],
+        'source_llvm': [],
+        'source_js': [],
         'source_c': [],
         'compile_c': [],
         'compile_llvm': [],
@@ -161,6 +163,12 @@
         self.ensure_backend('llvm')
         self.driver.source_llvm()
 
+    def source_js(self, argtypes=None, **kwds):
+        self.update_options(argtypes, kwds)
+        self.ensure_backend('js')
+        self.driver.source_js()
+        print open(str(self.driver.gen.filename)).read()
+
     def source_cl(self, argtypes=None, **kwds):
         self.update_options(argtypes, kwds)
         self.ensure_backend('cl')


From ericvrp at codespeak.net  Tue May 16 21:16:11 2006
From: ericvrp at codespeak.net (ericvrp at codespeak.net)
Date: Tue, 16 May 2006 21:16:11 +0200 (CEST)
Subject: [pypy-svn] r27299 - in pypy/dist/pypy/translator: . goal
Message-ID: <20060516191611.F15FC10068@code0.codespeak.net>

Author: ericvrp
Date: Tue May 16 21:16:10 2006
New Revision: 27299

Modified:
   pypy/dist/pypy/translator/driver.py
   pypy/dist/pypy/translator/goal/translate.py
Log:
Added option to translate with raisingop2direct_call transformation enabled.


Modified: pypy/dist/pypy/translator/driver.py
==============================================================================
--- pypy/dist/pypy/translator/driver.py	(original)
+++ pypy/dist/pypy/translator/driver.py	Tue May 16 21:16:10 2006
@@ -25,6 +25,7 @@
   'backend': 'c',
   'lowmem': False,
   'fork_before': None,
+  'raisingop2direct_call' : False,
   'merge_if_blocks': True
 })
 
@@ -205,6 +206,7 @@
         from pypy.translator.backendopt.all import backend_optimizations
         opt = self.options
         backend_optimizations(self.translator,
+                              raisingop2direct_call_all=opt.raisingop2direct_call,
                               merge_if_blocks_to_switch=opt.merge_if_blocks)
     #
     task_backendopt = taskdef(task_backendopt, 

Modified: pypy/dist/pypy/translator/goal/translate.py
==============================================================================
--- pypy/dist/pypy/translator/goal/translate.py	(original)
+++ pypy/dist/pypy/translator/goal/translate.py	Tue May 16 21:16:10 2006
@@ -52,6 +52,7 @@
     '3_stackless': [OPT(('--new-stackless',), "Stackless code generation (graph transformer)", True)],
     '4_stackless': [OPT(('--stackless',), "Stackless code generation (old GenC way)", 'old')],
     '5_merge_if_blocks': [OPT(('--no-if-blocks-merge',), "Do not merge if ... elif ... chains and use a switch statement for them.", False)],
+    '6_raisingop2direct_call': [OPT(('--raisingop2direct_call',), "Convert possible exception raising operations to direct calls.", True)],
     },
 
 
@@ -103,6 +104,7 @@
     'gc': 'boehm',
     'backend': 'c',
     'stackless': False,
+    'raisingop2direct_call' : False,
     'merge_if_blocks': True,
     
     'batch': False,


From arigo at codespeak.net  Tue May 16 21:16:55 2006
From: arigo at codespeak.net (arigo at codespeak.net)
Date: Tue, 16 May 2006 21:16:55 +0200 (CEST)
Subject: [pypy-svn] r27300 - in pypy/dist/pypy/translator: . c goal
Message-ID: <20060516191655.7F9D410068@code0.codespeak.net>

Author: arigo
Date: Tue May 16 21:16:53 2006
New Revision: 27300

Modified:
   pypy/dist/pypy/translator/c/database.py
   pypy/dist/pypy/translator/driver.py
   pypy/dist/pypy/translator/goal/targetgcbench.py
   pypy/dist/pypy/translator/goal/translate.py
Log:
Added the option  --gc=stacklessgc  to translate.py.  Some clean-up of way this option is parsed.


Modified: pypy/dist/pypy/translator/c/database.py
==============================================================================
--- pypy/dist/pypy/translator/c/database.py	(original)
+++ pypy/dist/pypy/translator/c/database.py	Tue May 16 21:16:53 2006
@@ -40,26 +40,25 @@
         self.namespace = CNameManager()
         if not standalone:
             self.pyobjmaker = PyObjMaker(self.namespace, self.get, translator)
-        if gcpolicy is None:
+
+        gcpolicy = gcpolicy or conftest.option.gcpolicy or 'ref'
+        if isinstance(gcpolicy, str):
             from pypy.translator.c import gc
-            polname = conftest.option.gcpolicy
-            if polname is not None:
-                if polname == 'boehm':
-                    gcpolicy = gc.BoehmGcPolicy
-                elif polname == 'exact_boehm':
-                    gcpolicy = gc.MoreExactBoehmGcPolicy
-                elif polname == 'ref':
-                    gcpolicy = gc.RefcountingGcPolicy
-                elif polname == 'none':
-                    gcpolicy = gc.NoneGcPolicy
-                elif polname == 'framework':
-                    gcpolicy = gc.FrameworkGcPolicy
-                elif polname == 'stacklessgc':
-                    gcpolicy = gc.StacklessFrameworkGcPolicy
-                else:
-                    assert False, "unknown gc policy %r"%polname
-            else:
+            polname = gcpolicy
+            if polname == 'boehm':
+                gcpolicy = gc.BoehmGcPolicy
+            elif polname == 'exact_boehm':
+                gcpolicy = gc.MoreExactBoehmGcPolicy
+            elif polname == 'ref':
                 gcpolicy = gc.RefcountingGcPolicy
+            elif polname == 'none':
+                gcpolicy = gc.NoneGcPolicy
+            elif polname == 'framework':
+                gcpolicy = gc.FrameworkGcPolicy
+            elif polname == 'stacklessgc':
+                gcpolicy = gc.StacklessFrameworkGcPolicy
+            else:
+                assert False, "unknown gc policy %r"%polname
         if translator is None or translator.rtyper is None:
             self.exctransformer = None
         else:

Modified: pypy/dist/pypy/translator/driver.py
==============================================================================
--- pypy/dist/pypy/translator/driver.py	(original)
+++ pypy/dist/pypy/translator/driver.py	Tue May 16 21:16:53 2006
@@ -228,26 +228,13 @@
             translator.frozen = True
 
         standalone = self.standalone
-        gcpolicy = None
-        if opt.gc =='boehm':
-            from pypy.translator.c import gc
-            gcpolicy = gc.BoehmGcPolicy
-        if opt.gc =='exact_boehm':
-            from pypy.translator.c import gc
-            gcpolicy = gc.MoreExactBoehmGcPolicy
-        if opt.gc == 'none':
-            from pypy.translator.c import gc
-            gcpolicy = gc.NoneGcPolicy
-        if opt.gc == 'framework':
-            from pypy.translator.c import gc
-            gcpolicy = gc.FrameworkGcPolicy
 
         if standalone:
             from pypy.translator.c.genc import CStandaloneBuilder as CBuilder
         else:
             from pypy.translator.c.genc import CExtModuleBuilder as CBuilder
         cbuilder = CBuilder(self.translator, self.entry_point,
-                            gcpolicy       = gcpolicy,
+                            gcpolicy       = opt.gc,
                             thread_enabled = getattr(opt, 'thread', False))
         cbuilder.stackless = opt.stackless
         if not standalone:     # xxx more messy

Modified: pypy/dist/pypy/translator/goal/targetgcbench.py
==============================================================================
--- pypy/dist/pypy/translator/goal/targetgcbench.py	(original)
+++ pypy/dist/pypy/translator/goal/targetgcbench.py	Tue May 16 21:16:53 2006
@@ -2,7 +2,13 @@
 from pypy.translator.goal import gcbench
 
 def entry_point(argv):
-    gcbench.main()
+    if len(argv) > 1:
+        n = int(argv[1])
+    else:
+        n = 1
+    while n > 0:
+        gcbench.main()
+        n -= 1
     return 0
 
 # _____ Define and setup target ___

Modified: pypy/dist/pypy/translator/goal/translate.py
==============================================================================
--- pypy/dist/pypy/translator/goal/translate.py	(original)
+++ pypy/dist/pypy/translator/goal/translate.py	Tue May 16 21:16:53 2006
@@ -48,7 +48,7 @@
 
     '1_backend': [OPT(('-b', '--backend'), "Backend", ['c', 'llvm', 'cl', 'squeak', 'js'])],
 
-    '2_gc': [OPT(('--gc',), "Garbage collector", ['boehm', 'ref', 'framework', 'none', 'exact_boehm'])],
+    '2_gc': [OPT(('--gc',), "Garbage collector", ['boehm', 'ref', 'framework', 'none', 'exact_boehm', 'stacklessgc'])],
     '3_stackless': [OPT(('--new-stackless',), "Stackless code generation (graph transformer)", True)],
     '4_stackless': [OPT(('--stackless',), "Stackless code generation (old GenC way)", 'old')],
     '5_merge_if_blocks': [OPT(('--no-if-blocks-merge',), "Do not merge if ... elif ... chains and use a switch statement for them.", False)],


From ericvrp at codespeak.net  Tue May 16 21:20:06 2006
From: ericvrp at codespeak.net (ericvrp at codespeak.net)
Date: Tue, 16 May 2006 21:20:06 +0200 (CEST)
Subject: [pypy-svn] r27301 - pypy/dist/pypy/translator/c
Message-ID: <20060516192006.250331008E@code0.codespeak.net>

Author: ericvrp
Date: Tue May 16 21:20:05 2006
New Revision: 27301

Modified:
   pypy/dist/pypy/translator/c/exceptiontransform.py
Log:
Made create_exception_handling return some counters to make it easier
for the backends to show just the graphs that were transformed.
This was nice to have while trying to use this transformation in genllvm.


Modified: pypy/dist/pypy/translator/c/exceptiontransform.py
==============================================================================
--- pypy/dist/pypy/translator/c/exceptiontransform.py	(original)
+++ pypy/dist/pypy/translator/c/exceptiontransform.py	Tue May 16 21:20:05 2006
@@ -141,23 +141,28 @@
         self.seen_graphs[graph] = True
         join_blocks(graph)
         # collect the blocks before changing them
+        n_need_exc_matching_blocks = 0
+        n_gen_exc_checks           = 0
         for block in list(graph.iterblocks()):
-            self.transform_block(graph, block)
+            need_exc_matching, gen_exc_checks = self.transform_block(graph, block)
+            n_need_exc_matching_blocks += need_exc_matching
+            n_gen_exc_checks           += gen_exc_checks
         self.transform_except_block(graph, graph.exceptblock)
         cleanup_graph(graph)
         removenoops.remove_superfluous_keep_alive(graph)
+        return n_need_exc_matching_blocks, n_gen_exc_checks
 
     def transform_block(self, graph, block):
+        need_exc_matching = False
+        n_gen_exc_checks = 0
         if block is graph.exceptblock:
-            return
+            return need_exc_matching, n_gen_exc_checks
         elif block is graph.returnblock:
-            return
+            return need_exc_matching, n_gen_exc_checks
         last_operation = len(block.operations) - 1
         if block.exitswitch == c_last_exception:
             need_exc_matching = True
             last_operation -= 1
-        else:
-            need_exc_matching = False
         lastblock = block
         for i in range(last_operation, -1, -1):
             op = block.operations[i]
@@ -170,6 +175,7 @@
                 lastblock = afterblock
 
             self.gen_exc_check(block, graph.returnblock)                
+            n_gen_exc_checks += 1
 
             #non-exception case
             block.exits[0].exitcase = block.exits[0].llexitcase = False
@@ -184,6 +190,7 @@
                 lastblock.exits[0].exitcase = None
             else:
                 self.insert_matching(lastblock, graph)
+        return need_exc_matching, n_gen_exc_checks
 
     def transform_except_block(self, graph, block):
         # attach an except block -- let's hope that nobody uses it


From arigo at codespeak.net  Tue May 16 21:26:45 2006
From: arigo at codespeak.net (arigo at codespeak.net)
Date: Tue, 16 May 2006 21:26:45 +0200 (CEST)
Subject: [pypy-svn] r27302 - pypy/dist/pypy/translator/c
Message-ID: <20060516192645.E04671008E@code0.codespeak.net>

Author: arigo
Date: Tue May 16 21:26:44 2006
New Revision: 27302

Modified:
   pypy/dist/pypy/translator/c/funcgen.py
Log:
Generate goto's in a more natural-looking order (when reading the C source).
Remove double blank lines.


Modified: pypy/dist/pypy/translator/c/funcgen.py
==============================================================================
--- pypy/dist/pypy/translator/c/funcgen.py	(original)
+++ pypy/dist/pypy/translator/c/funcgen.py	Tue May 16 21:26:44 2006
@@ -233,14 +233,13 @@
                 assert len(block.exits) == 1
                 for op in self.gen_link(block.exits[0]):
                     yield op
-                yield ''
             else:
                 assert block.exitswitch != c_last_exception
                 # block ending in a switch on a value
                 TYPE = self.lltypemap(block.exitswitch)
                 if TYPE in (Bool, PyObjPtr):
                     expr = self.expr(block.exitswitch)
-                    for link in block.exits[:-1]:
+                    for link in block.exits[:0:-1]:
                         assert link.exitcase in (False, True)
                         if TYPE == Bool:
                             if not link.exitcase:
@@ -256,13 +255,12 @@
                         for op in self.gen_link(link):
                             yield '\t' + op
                         yield '}'
-                    link = block.exits[-1]
+                    link = block.exits[0]
                     assert link.exitcase in (False, True)
                     #yield 'assert(%s == %s);' % (self.expr(block.exitswitch),
                     #                       self.genc.nameofvalue(link.exitcase, ct))
-                    for op in self.gen_link(block.exits[-1]):
+                    for op in self.gen_link(link):
                         yield op
-                    yield ''
                 elif TYPE in (Signed, Unsigned, SignedLongLong,
                               UnsignedLongLong, Char, UniChar):
                     defaultlink = None


From arigo at codespeak.net  Tue May 16 21:43:01 2006
From: arigo at codespeak.net (arigo at codespeak.net)
Date: Tue, 16 May 2006 21:43:01 +0200 (CEST)
Subject: [pypy-svn] r27303 - pypy/dist/pypy/rpython/memory
Message-ID: <20060516194301.8C14E1008E@code0.codespeak.net>

Author: arigo
Date: Tue May 16 21:43:00 2006
New Revision: 27303

Modified:
   pypy/dist/pypy/rpython/memory/gc.py
Log:
Print the total time spent collecting too.  Aren't we nice.


Modified: pypy/dist/pypy/rpython/memory/gc.py
==============================================================================
--- pypy/dist/pypy/rpython/memory/gc.py	(original)
+++ pypy/dist/pypy/rpython/memory/gc.py	Tue May 16 21:43:00 2006
@@ -115,6 +115,7 @@
         self.heap_usage = 0          # at the end of the latest collection
         self.bytes_malloced = 0      # since the latest collection
         self.bytes_malloced_threshold = start_heap_size
+        self.total_collection_time = 0.0
         #need to maintain a list of malloced objects, since we used the systems
         #allocator and can't walk the heap
         self.malloced_objects = None
@@ -171,8 +172,9 @@
         return llmemory.cast_adr_to_ptr(result, llmemory.GCREF)
 
     def collect(self):
-        import os
+        import os, time
         os.write(2, 'collecting...\n')
+        start_time = time.time()
         roots = self.get_roots()
         objects = self.AddressLinkedList()
         while 1:
@@ -249,6 +251,8 @@
         self.malloced_objects = newmo
         if curr_heap_size > self.bytes_malloced_threshold:
             self.bytes_malloced_threshold = curr_heap_size
+        end_time = time.time()
+        self.total_collection_time += end_time - start_time
         # warning, the following debug print allocates memory to manipulate
         # the strings!  so it must be at the end
         os.write(2, "  malloced since previous collection: %s bytes\n" %
@@ -259,6 +263,8 @@
                  freed_size)
         os.write(2, "  new heap usage:                     %s bytes\n" %
                  curr_heap_size)
+        os.write(2, "  total time spent collecting:        %s seconds\n" %
+                 self.total_collection_time)
         assert self.heap_usage + old_malloced == curr_heap_size + freed_size
         self.heap_usage = curr_heap_size
 


From ericvrp at codespeak.net  Tue May 16 21:55:35 2006
From: ericvrp at codespeak.net (ericvrp at codespeak.net)
Date: Tue, 16 May 2006 21:55:35 +0200 (CEST)
Subject: [pypy-svn] r27304 - pypy/dist/pypy/translator/goal
Message-ID: <20060516195535.4A25D10094@code0.codespeak.net>

Author: ericvrp
Date: Tue May 16 21:55:34 2006
New Revision: 27304

Modified:
   pypy/dist/pypy/translator/goal/bench-cronjob.py
Log:
Store (nightly benchmark) .ll, .bc and .s files into an archive directory for later inspection.


Modified: pypy/dist/pypy/translator/goal/bench-cronjob.py
==============================================================================
--- pypy/dist/pypy/translator/goal/bench-cronjob.py	(original)
+++ pypy/dist/pypy/translator/goal/bench-cronjob.py	Tue May 16 21:55:34 2006
@@ -47,11 +47,19 @@
     print cmd
     os.system(cmd)
 
+    cmd = "cp %s.c pypy/translator/goal/archive" % b
+    print cmd
+    os.system(cmd)
+
     cmd = "gcc %s.c -S -O3 -fomit-frame-pointer -o %s.s" % (b, b)
     print cmd
     os.system(cmd)
 
-    cmd = "gcc %s.s -static -lgc -lm -lpthread -pipe -o %s" % (b, b)
+    cmd = "cp %s.s pypy/translator/goal/archive" % b
+    print cmd
+    os.system(cmd)
+
+    cmd = "gcc %s.s -lgc -lm -lpthread -pipe -o %s" % (b, b) #XXX -static
     print cmd
     os.system(cmd)
 
@@ -70,11 +78,7 @@
     print cmd
     os.system(cmd)
 
-    #cmd = "as %s.s -o %s.o" % (b, b)
-    #print cmd
-    #os.system(cmd)
-
-    cmd = "gcc %s.s -static -lgc -lm -lpthread -pipe -o %s" % (b, b)
+    cmd = "gcc %s.s -lgc -lm -lpthread -pipe -o %s" % (b, b) #XXX -static
     print cmd
     os.system(cmd)
 
@@ -99,7 +103,6 @@
         translateoptions = ''
 
     os.chdir(homedir + '/projects/pypy-dist/pypy/translator/goal')
-    #os.system('cp ~/x/entry_point.ll %s/entry_point.ll' % tmpdir) #XXX
     os.system('/usr/local/bin/python translate.py --backend=%(backend)s%(featureoptions)s%(translateoptions)s --text --batch targetpypystandalone.py %(targetoptions)s 2>&1' % locals())
     os.system('mv %s/entry_point.ll %s/pypy.ll' % (tmpdir, tmpdir))
 


From arigo at codespeak.net  Tue May 16 23:10:32 2006
From: arigo at codespeak.net (arigo at codespeak.net)
Date: Tue, 16 May 2006 23:10:32 +0200 (CEST)
Subject: [pypy-svn] r27306 - pypy/dist/pypy/translator/c
Message-ID: <20060516211032.887B910050@code0.codespeak.net>

Author: arigo
Date: Tue May 16 23:10:31 2006
New Revision: 27306

Modified:
   pypy/dist/pypy/translator/c/genc.py
Log:
(arigo, pedronis)

add a profile target to our generated genc Makefile.



Modified: pypy/dist/pypy/translator/c/genc.py
==============================================================================
--- pypy/dist/pypy/translator/c/genc.py	(original)
+++ pypy/dist/pypy/translator/c/genc.py	Tue May 16 23:10:31 2006
@@ -797,4 +797,7 @@
 
 debug: clean
 \tmake CFLAGS="-g -pthread"
+
+profile: clean
+\tmake CFLAGS="-pg $(CFLAGS)" LDFLAGS="-pg $(LDFLAGS)"
 '''


From arigo at codespeak.net  Tue May 16 23:12:49 2006
From: arigo at codespeak.net (arigo at codespeak.net)
Date: Tue, 16 May 2006 23:12:49 +0200 (CEST)
Subject: [pypy-svn] r27307 - pypy/dist/pypy/translator/c/src
Message-ID: <20060516211249.A185C1006B@code0.codespeak.net>

Author: arigo
Date: Tue May 16 23:12:48 2006
New Revision: 27307

Modified:
   pypy/dist/pypy/translator/c/src/address.h
   pypy/dist/pypy/translator/c/src/mem.h
Log:
(arigo, pedronis)

obscure, raw_malloc which is used by our framework gc
was not really using obmalloc as we expected.

obscure fix and move the RAW ops to mem.h 



Modified: pypy/dist/pypy/translator/c/src/address.h
==============================================================================
--- pypy/dist/pypy/translator/c/src/address.h	(original)
+++ pypy/dist/pypy/translator/c/src/address.h	Tue May 16 23:12:48 2006
@@ -16,20 +16,3 @@
 #define OP_ADR_LT(x,y,r)	  r = ((x) <  (y))
 #define OP_ADR_GE(x,y,r)	  r = ((x) >= (y))
 
-#define OP_RAW_MALLOC(size,r)                                          \
-    r = (void*) calloc(1, size);                                       \
-    if (r == NULL) FAIL_EXCEPTION( PyExc_MemoryError, "out of memory");\
-
-#define OP_RAW_MALLOC_USAGE(size, r) r = size
-
-#ifdef MS_WINDOWS
-#define alloca  _alloca
-#endif
-
-#define OP_STACK_MALLOC(size,r)                                            \
-    r = (void*) alloca(size);                                              \
-    if (r == NULL) FAIL_EXCEPTION(PyExc_MemoryError, "out of memory");\
- 
-#define OP_RAW_FREE(x,r)        free(x);
-#define OP_RAW_MEMCOPY(x,y,size,r) memcpy(y,x,size);
-

Modified: pypy/dist/pypy/translator/c/src/mem.h
==============================================================================
--- pypy/dist/pypy/translator/c/src/mem.h	(original)
+++ pypy/dist/pypy/translator/c/src/mem.h	Tue May 16 23:12:48 2006
@@ -2,6 +2,22 @@
 /************************************************************/
  /***  C header subsection: operations on LowLevelTypes    ***/
 
+#define OP_RAW_MALLOC(size,r) OP_ZERO_MALLOC(size, r)
+
+#define OP_RAW_MALLOC_USAGE(size, r) r = size
+
+#ifdef MS_WINDOWS
+#define alloca  _alloca
+#endif
+
+#define OP_STACK_MALLOC(size,r)                                            \
+    r = (void*) alloca(size);                                              \
+    if (r == NULL) FAIL_EXCEPTION(PyExc_MemoryError, "out of memory");\
+ 
+#define OP_RAW_FREE(x,r)        OP_FREE(x)
+#define OP_RAW_MEMCOPY(x,y,size,r) memcpy(y,x,size);
+
+/************************************************************/
 
 /* a reasonably safe bound on the largest allowed argument value
    that we can pass to malloc.  This is used for var-sized mallocs


From cfbolz at codespeak.net  Wed May 17 01:01:21 2006
From: cfbolz at codespeak.net (cfbolz at codespeak.net)
Date: Wed, 17 May 2006 01:01:21 +0200 (CEST)
Subject: [pypy-svn] r27312 - in pypy/dist/pypy: annotation module/_weakref
	rpython rpython/lltypesystem rpython/lltypesystem/test
	rpython/memory rpython/memory/test translator/c translator/c/test
Message-ID: <20060516230121.06B9B1009D@code0.codespeak.net>

Author: cfbolz
Date: Wed May 17 01:01:11 2006
New Revision: 27312

Modified:
   pypy/dist/pypy/annotation/binaryop.py
   pypy/dist/pypy/annotation/bookkeeper.py
   pypy/dist/pypy/annotation/model.py
   pypy/dist/pypy/module/_weakref/interp__weakref.py
   pypy/dist/pypy/rpython/lltypesystem/llmemory.py
   pypy/dist/pypy/rpython/lltypesystem/test/test_llmemory.py
   pypy/dist/pypy/rpython/memory/gctransform.py
   pypy/dist/pypy/rpython/memory/test/test_address.py
   pypy/dist/pypy/rpython/objectmodel.py
   pypy/dist/pypy/translator/c/exceptiontransform.py
   pypy/dist/pypy/translator/c/funcgen.py
   pypy/dist/pypy/translator/c/gc.py
   pypy/dist/pypy/translator/c/primitive.py
   pypy/dist/pypy/translator/c/test/test_boehm.py
   pypy/dist/pypy/translator/c/test/test_lladdresses.py
   pypy/dist/pypy/translator/c/test/test_newgc.py
Log:
make weak addresses compilable. phew. lots of stuff missing.  adapt _weakref to
use weak addresses to hopefully make it possible to use weakrefs with boehm
too.


Modified: pypy/dist/pypy/annotation/binaryop.py
==============================================================================
--- pypy/dist/pypy/annotation/binaryop.py	(original)
+++ pypy/dist/pypy/annotation/binaryop.py	Wed May 17 01:01:11 2006
@@ -13,6 +13,7 @@
 from pypy.annotation.model import SomePBC, SomeSlice, SomeFloat, s_None
 from pypy.annotation.model import SomeExternalObject
 from pypy.annotation.model import SomeAddress, SomeTypedAddressAccess
+from pypy.annotation.model import SomeWeakGcAddress
 from pypy.annotation.model import SomeCTypesObject
 from pypy.annotation.model import unionof, UnionError, set, missing_operation, TLS
 from pypy.annotation.model import add_knowntypedata, merge_knowntypedata
@@ -759,6 +760,12 @@
     def union((s_obj, s_addr)):
         raise UnionError, "union of address and anything else makes no sense"
 
+
+class __extend__(pairtype(SomeWeakGcAddress, SomeWeakGcAddress)):
+    def union((s_addr1, s_addr2)):
+        return SomeWeakGcAddress()
+    
+
 class __extend__(pairtype(SomeCTypesObject, SomeInteger)):
     def setitem((s_cto, s_index), s_value):
         pass

Modified: pypy/dist/pypy/annotation/bookkeeper.py
==============================================================================
--- pypy/dist/pypy/annotation/bookkeeper.py	(original)
+++ pypy/dist/pypy/annotation/bookkeeper.py	Wed May 17 01:01:11 2006
@@ -11,7 +11,7 @@
      SomeInteger, SomeExternalObject, SomeOOInstance, TLS, SomeAddress, \
      SomeUnicodeCodePoint, SomeOOStaticMeth, s_None, s_ImpossibleValue, \
      SomeLLADTMeth, SomeBool, SomeTuple, SomeOOClass, SomeImpossibleValue, \
-     SomeList, SomeObject
+     SomeList, SomeObject, SomeWeakGcAddress
 from pypy.annotation.classdef import ClassDef, InstanceSource
 from pypy.annotation.listdef import ListDef, MOST_GENERAL_LISTDEF
 from pypy.annotation.dictdef import DictDef, MOST_GENERAL_DICTDEF
@@ -365,6 +365,9 @@
             result = SomePtr(lltype.typeOf(x))
         elif isinstance(x, llmemory.fakeaddress):
             result = SomeAddress(is_null=not x)
+        elif isinstance(x, llmemory.fakeweakaddress):
+            assert x.ref is None # only WEAKNULL allowed
+            result = SomeWeakGcAddress()
         elif isinstance(x, ootype._static_meth):
             result = SomeOOStaticMeth(ootype.typeOf(x))
         elif isinstance(x, ootype._class):

Modified: pypy/dist/pypy/annotation/model.py
==============================================================================
--- pypy/dist/pypy/annotation/model.py	(original)
+++ pypy/dist/pypy/annotation/model.py	Wed May 17 01:01:11 2006
@@ -481,6 +481,7 @@
 class SomePtr(SomeObject):
     immutable = True
     def __init__(self, ll_ptrtype):
+        assert isinstance(ll_ptrtype, lltype.Ptr)
         self.ll_ptrtype = ll_ptrtype
 
     def can_be_none(self):
@@ -526,6 +527,7 @@
     (SomeChar(), lltype.Char),
     (SomeUnicodeCodePoint(), lltype.UniChar),
     (SomeAddress(), llmemory.Address),
+    (SomeWeakGcAddress(), llmemory.WeakGcAddress),
 ]
 
 def annotation_to_lltype(s_val, info=None):

Modified: pypy/dist/pypy/module/_weakref/interp__weakref.py
==============================================================================
--- pypy/dist/pypy/module/_weakref/interp__weakref.py	(original)
+++ pypy/dist/pypy/module/_weakref/interp__weakref.py	Wed May 17 01:01:11 2006
@@ -4,8 +4,8 @@
 from pypy.interpreter.error import OperationError
 from pypy.interpreter.typedef import GetSetProperty, TypeDef
 from pypy.interpreter.gateway import interp2app, ObjSpace
-from pypy.rpython.objectmodel import cast_address_to_object, cast_object_to_address
-from pypy.rpython.lltypesystem.llmemory import NULL
+from pypy.rpython.objectmodel import cast_weakgcaddress_to_object, cast_object_to_weakgcaddress
+from pypy.rpython.lltypesystem.llmemory import WEAKNULL
 
 
 class WeakrefLifeline(object):
@@ -17,13 +17,12 @@
     def __del__(self):
         for i in range(len(self.addr_refs) - 1, -1, -1):
             addr_ref = self.addr_refs[i]
-            if addr_ref != NULL:
-                w_ref = cast_address_to_object(addr_ref, W_WeakrefBase)
+            if cast_weakgcaddress_to_object(addr_ref, W_Root) is not None:
+                w_ref = cast_weakgcaddress_to_object(addr_ref, W_Root)
                 w_ref.invalidate()
         for i in range(len(self.addr_refs) - 1, -1, -1):
-            addr_ref = self.addr_refs[i]
-            if addr_ref != NULL:
-                w_ref = cast_address_to_object(addr_ref, W_WeakrefBase)
+            if cast_weakgcaddress_to_object(addr_ref, W_Root) is not None:
+                w_ref = cast_weakgcaddress_to_object(addr_ref, W_Root)
                 w_ref.activate_callback()
     
     def get_weakref(self, space, w_subtype, w_obj, w_callable):
@@ -32,12 +31,12 @@
         can_reuse = space.is_w(w_callable, space.w_None)
         if is_weakreftype and can_reuse and self.cached_weakref_index >= 0:
             cached_weakref_address = self.addr_refs[self.cached_weakref_index]
-            return cast_address_to_object(cached_weakref_address, W_Weakref)
+            return cast_weakgcaddress_to_object(cached_weakref_address, W_Weakref)
         w_ref = space.allocate_instance(W_Weakref, w_subtype)
         index = len(self.addr_refs)
         W_Weakref.__init__(w_ref, space, self, index,
                            w_obj, w_callable)
-        self.addr_refs.append(cast_object_to_address(w_ref))
+        self.addr_refs.append(cast_object_to_weakgcaddress(w_ref))
         if is_weakreftype and can_reuse:
             self.cached_weakref_index = index
         return w_ref
@@ -46,19 +45,19 @@
         can_reuse = space.is_w(w_callable, space.w_None)
         if can_reuse and self.cached_proxy_index >= 0:
             cached_proxy_address = self.addr_refs[self.cached_proxy_index]
-            return cast_address_to_object(cached_proxy_address, W_Proxy)
+            return cast_weakgcaddress_to_object(cached_proxy_address, W_Proxy)
         index = len(self.addr_refs)
         if space.is_true(space.callable(w_obj)):
             w_proxy = W_CallableProxy(space, self, index, w_obj, w_callable)
         else:
             w_proxy = W_Proxy(space, self, index, w_obj, w_callable)
-        self.addr_refs.append(cast_object_to_address(w_proxy))
+        self.addr_refs.append(cast_object_to_weakgcaddress(w_proxy))
         if can_reuse:
             self.cached_proxy_index = index
         return w_proxy
 
     def ref_is_dead(self, index):
-        self.addr_refs[index] = NULL
+        self.addr_refs[index] = WEAKNULL
         if self.cached_proxy_index == index:
             self.cached_proxy_index = -1
         if self.cached_weakref_index == index:
@@ -66,13 +65,13 @@
 
     def get_any_weakref(self, space):
         if self.cached_weakref_index != -1:
-            return cast_address_to_object(
-                self.addr_refs[self.cached_weakref_index], W_WeakrefBase)
+            return cast_weakgcaddress_to_object(
+                self.addr_refs[self.cached_weakref_index], W_Root)
         w_weakreftype = space.gettypeobject(W_Weakref.typedef)
         for i in range(len(self.addr_refs)):
             addr = self.addr_refs[i]
-            if addr != NULL:
-                w_ref = cast_address_to_object(addr, W_WeakrefBase)
+            if cast_weakgcaddress_to_object(addr, W_Root) is not None:
+                w_ref = cast_weakgcaddress_to_object(addr, W_Root)
                 if space.is_true(space.isinstance(w_ref, w_weakreftype)):
                     return w_ref
         return space.w_None
@@ -80,18 +79,18 @@
 class W_WeakrefBase(Wrappable):
     def __init__(w_self, space, lifeline, index, w_obj, w_callable):
         w_self.space = space
-        w_self.address = cast_object_to_address(w_obj)
+        w_self.address = cast_object_to_weakgcaddress(w_obj)
         w_self.w_callable = w_callable
-        w_self.addr_lifeline = cast_object_to_address(lifeline)
+        w_self.addr_lifeline = cast_object_to_weakgcaddress(lifeline)
         w_self.index = index
 
     def dereference(self):
-        if self.address == NULL:
+        if cast_weakgcaddress_to_object(self.address, W_Root) is None:
             return self.space.w_None
-        return cast_address_to_object(self.address, W_Root)
+        return cast_weakgcaddress_to_object(self.address, W_Root)
         
     def invalidate(w_self):
-        w_self.address = NULL
+        w_self.address = WEAKNULL
 
     def activate_callback(w_self):
         if not w_self.space.is_w(w_self.w_callable, w_self.space.w_None):
@@ -101,9 +100,9 @@
                 e.write_unraisable(w_self.space, 'function', w_self.w_callable)
 
     def __del__(w_self):
-        if w_self.address != NULL:
-            lifeline = cast_address_to_object(w_self.addr_lifeline,
-                                              WeakrefLifeline)
+        lifeline = cast_weakgcaddress_to_object(w_self.addr_lifeline,
+                                                WeakrefLifeline)
+        if lifeline is not None:
             lifeline.ref_is_dead(w_self.index)
 
 class W_Weakref(W_WeakrefBase):
@@ -129,7 +128,8 @@
     return lifeline.get_weakref(space, w_subtype, w_obj, w_callable)
 
 def descr__eq__(space, ref1, ref2):
-    if ref1.address == NULL or ref2.address == NULL:
+    if (cast_weakgcaddress_to_object(ref1.address, W_Root) is None or
+        cast_weakgcaddress_to_object(ref2.address, W_Root) is None):
         return space.is_(ref1, ref2)
     return space.eq(ref1.dereference(), ref2.dereference())
 
@@ -154,7 +154,7 @@
     else:
         result = 0
         for i in range(len(lifeline.addr_refs)):
-            if lifeline.addr_refs[i] != NULL:
+            if cast_weakgcaddress_to_object(lifeline.addr_refs[i], W_Root) is not None:
                 result += 1
         return space.wrap(result)
 
@@ -166,8 +166,8 @@
         result = []
         for i in range(len(lifeline.addr_refs)):
             addr = lifeline.addr_refs[i]
-            if addr != NULL:
-                result.append(cast_address_to_object(addr, W_WeakrefBase))
+            if cast_weakgcaddress_to_object(addr, W_Root) is not None:
+                result.append(cast_weakgcaddress_to_object(addr, W_Root))
         return space.newlist(result)
 
 #_________________________________________________________________

Modified: pypy/dist/pypy/rpython/lltypesystem/llmemory.py
==============================================================================
--- pypy/dist/pypy/rpython/lltypesystem/llmemory.py	(original)
+++ pypy/dist/pypy/rpython/lltypesystem/llmemory.py	Wed May 17 01:01:11 2006
@@ -463,11 +463,17 @@
             self.ref = None
     def get(self):
         if self.ref is None:
-            raise NullAddressError
+            return None
         ob = self.ref()
         if ob is None:
             raise NullAddressError
         return ob
+    def __repr__(self):
+        if self.ref is None:
+            s = 'NULL'
+        else:
+            s = str(self.ref)
+        return '' % (s,)
 
 WeakGcAddress = lltype.Primitive("WeakGcAddress",
                                  fakeweakaddress(None))
@@ -477,9 +483,13 @@
     return fakeweakaddress(obj)
 
 def cast_weakadr_to_ptr(adr, EXPECTED_TYPE):
-    return adr.get()
+    result = adr.get()
+    if result is None:
+        return lltype.nullptr(EXPECTED_TYPE.TO)
+    return result
 
 fakeweakaddress._TYPE = WeakGcAddress
+WEAKNULL = fakeweakaddress(None)
 
 # ____________________________________________________________
 

Modified: pypy/dist/pypy/rpython/lltypesystem/test/test_llmemory.py
==============================================================================
--- pypy/dist/pypy/rpython/lltypesystem/test/test_llmemory.py	(original)
+++ pypy/dist/pypy/rpython/lltypesystem/test/test_llmemory.py	Wed May 17 01:01:11 2006
@@ -1,5 +1,6 @@
 from pypy.rpython.lltypesystem.llmemory import *
 from pypy.rpython.lltypesystem import lltype
+from pypy.rpython.test.test_llinterp import interpret
 import py
 
 def test_simple():
@@ -378,3 +379,32 @@
     s2_ptr = cast_adr_to_ptr(badr, SPTR)
     assert s2_ptr.x == 2
     # release(start)
+
+class TestWeakAddressLLinterp(object):
+    def test_null(self):
+        from pypy.rpython.objectmodel import cast_weakgcaddress_to_object
+        from pypy.rpython.objectmodel import cast_object_to_weakgcaddress
+        class A:
+            pass
+        def f():
+            return cast_weakgcaddress_to_object(WEAKNULL, A) is None
+        assert interpret(f, [])
+    
+    def test_attribute(object):
+        from pypy.rpython.objectmodel import cast_weakgcaddress_to_object
+        from pypy.rpython.objectmodel import cast_object_to_weakgcaddress
+        class A:
+            pass
+        class B:
+            pass
+        def f(x):
+            a = A()
+            b = B()
+            if x:
+                a.addr = WEAKNULL
+            else:
+                a.addr = cast_object_to_weakgcaddress(b)
+            return cast_weakgcaddress_to_object(a.addr, B) is b
+        assert not interpret(f, [1])
+        assert interpret(f, [0])
+ 

Modified: pypy/dist/pypy/rpython/memory/gctransform.py
==============================================================================
--- pypy/dist/pypy/rpython/memory/gctransform.py	(original)
+++ pypy/dist/pypy/rpython/memory/gctransform.py	Wed May 17 01:01:11 2006
@@ -651,6 +651,28 @@
         """ for boehm it is enough to do nothing"""
         return [SpaceOperation("same_as", [Constant(None, lltype.Void)], op.result)]
 
+    def replace_cast_ptr_to_weakadr(self, op, livevars, block):
+        result = []
+        intvar = varoftype(lltype.Signed)
+        invertvar = varoftype(lltype.Signed)
+        ptrvar = varoftype(op.args[0].concretetype)
+        result.append(SpaceOperation("cast_ptr_to_int", [op.args[0]], intvar))
+        result.append(SpaceOperation("int_invert", [intvar], invertvar))
+        result.append(SpaceOperation("cast_int_to_ptr", [invertvar], ptrvar))
+        result.append(SpaceOperation("cast_ptr_to_weakadr", [ptrvar], op.result))
+        return result
+
+    def replace_cast_weakadr_to_ptr(self, op, livevars, block):
+        result = []
+        intvar = varoftype(lltype.Signed)
+        invertvar = varoftype(lltype.Signed)
+        ptrvar = varoftype(op.args[0].concretetype)
+        result.append(SpaceOperation("cast_weakadr_to_ptr", [op.args[0]], ptrvar))
+        result.append(SpaceOperation("cast_ptr_to_int", [ptrvar], intvar))
+        result.append(SpaceOperation("int_invert", [intvar], invertvar))
+        result.append(SpaceOperation("cast_int_to_ptr", [invertvar], op.result))
+        return result
+
     def get_rtti(self, TYPE):
         if isinstance(TYPE, lltype.GcStruct):
             try:

Modified: pypy/dist/pypy/rpython/memory/test/test_address.py
==============================================================================
--- pypy/dist/pypy/rpython/memory/test/test_address.py	(original)
+++ pypy/dist/pypy/rpython/memory/test/test_address.py	Wed May 17 01:01:11 2006
@@ -9,7 +9,7 @@
 from pypy.rpython.memory.lladdress import _address, NULL
 from pypy.rpython.memory.lladdress import raw_malloc, raw_free, raw_memcopy
 from pypy.rpython.memory.lladdress import get_py_object, get_address_of_object
-from pypy.rpython.lltypesystem.llmemory import Address, NullAddressError
+from pypy.rpython.lltypesystem.llmemory import Address, NullAddressError, WEAKNULL
 from pypy.rpython.memory.simulator import MemorySimulatorError
 from pypy.rpython.memory.test.test_llinterpsim import interpret
 from pypy.rpython.lltypesystem import lltype
@@ -152,7 +152,7 @@
         s = a.build_types(f, [])
         assert isinstance(s, annmodel.SomeInteger)
         
-        
+       
 class TestAddressRTyping(object):
     def test_null(self):
         def f():

Modified: pypy/dist/pypy/rpython/objectmodel.py
==============================================================================
--- pypy/dist/pypy/rpython/objectmodel.py	(original)
+++ pypy/dist/pypy/rpython/objectmodel.py	Wed May 17 01:01:11 2006
@@ -63,16 +63,14 @@
     obj.__dict__ = {}
     obj.__class__ = FREED_OBJECT
 
-def cast_object_to_address(obj):
-    import weakref
-    from pypy.rpython.lltypesystem.llmemory import fakeaddress
-    return fakeaddress(weakref.ref(obj))
+def cast_object_to_weakgcaddress(obj):
+    from pypy.rpython.lltypesystem.llmemory import fakeweakaddress
+    return fakeweakaddress(obj)
 
-def cast_address_to_object(address, expected_result):
-    if not address:  # NULL address
+def cast_weakgcaddress_to_object(address, expected_result):
+    if address.ref is None:  # NULL address
         return None
-    wref = address.ref().get()
-    obj = wref()
+    obj = address.get()
     assert obj is not None
     assert isinstance(obj, expected_result)
     return obj
@@ -80,32 +78,32 @@
 from pypy.rpython.extregistry import ExtRegistryEntry
 
 class Entry(ExtRegistryEntry):
-    _about_ = cast_object_to_address
+    _about_ = cast_object_to_weakgcaddress
 
     def compute_result_annotation(self, s_obj):
         from pypy.annotation import model as annmodel
-        return annmodel.SomeAddress()
+        return annmodel.SomeWeakGcAddress()
 
     def specialize_call(self, hop):
         vlist = hop.inputargs(hop.args_r[0])
-        return hop.genop('cast_ptr_to_adr', vlist,
+        return hop.genop('cast_ptr_to_weakadr', vlist,
                          resulttype=hop.r_result.lowleveltype)
 
 class Entry(ExtRegistryEntry):
-    _about_ = cast_address_to_object
+    _about_ = cast_weakgcaddress_to_object
 
     def compute_result_annotation(self, s_int, s_clspbc):
         from pypy.annotation import model as annmodel
         assert len(s_clspbc.descriptions) == 1
         desc = s_clspbc.descriptions.keys()[0]
         cdef = desc.getuniqueclassdef()
-        return annmodel.SomeInstance(cdef)
+        return annmodel.SomeInstance(cdef, can_be_None=True)
 
     def specialize_call(self, hop):
         from pypy.rpython import raddress
-        assert isinstance(hop.args_r[0], raddress.AddressRepr)
-        vlist = [hop.inputarg(raddress.address_repr, arg=0)]
-        return hop.genop('cast_adr_to_ptr', vlist,
+        assert isinstance(hop.args_r[0], raddress.WeakGcAddressRepr)
+        vlist = [hop.inputarg(raddress.weakgcaddress_repr, arg=0)]
+        return hop.genop('cast_weakadr_to_ptr', vlist,
                          resulttype = hop.r_result.lowleveltype)
 
 

Modified: pypy/dist/pypy/translator/c/exceptiontransform.py
==============================================================================
--- pypy/dist/pypy/translator/c/exceptiontransform.py	(original)
+++ pypy/dist/pypy/translator/c/exceptiontransform.py	Wed May 17 01:01:11 2006
@@ -21,6 +21,7 @@
                        lltype.UniChar: unichr(0xFFFF), # XXX is this always right?
                        lltype.Bool: True,
                        llmemory.Address: NULL,
+                       llmemory.WeakGcAddress: llmemory.fakeweakaddress(None),
                        lltype.Void: None}
 
 def error_value(T):

Modified: pypy/dist/pypy/translator/c/funcgen.py
==============================================================================
--- pypy/dist/pypy/translator/c/funcgen.py	(original)
+++ pypy/dist/pypy/translator/c/funcgen.py	Wed May 17 01:01:11 2006
@@ -594,6 +594,9 @@
     OP_CAST_PTR_TO_ADR = OP_CAST_POINTER
     OP_CAST_ADR_TO_PTR = OP_CAST_POINTER
     OP_CAST_OPAQUE_PTR = OP_CAST_POINTER
+    OP_CAST_PTR_TO_WEAKADR = OP_CAST_POINTER
+    OP_CAST_WEAKADR_TO_PTR = OP_CAST_POINTER
+
 
     def OP_CAST_INT_TO_PTR(self, op):
         TYPE = self.lltypemap(op.result)

Modified: pypy/dist/pypy/translator/c/gc.py
==============================================================================
--- pypy/dist/pypy/translator/c/gc.py	(original)
+++ pypy/dist/pypy/translator/c/gc.py	Wed May 17 01:01:11 2006
@@ -234,7 +234,6 @@
     def OP_GC__COLLECT(self, funcgen, op):
         return 'GC_gcollect(); GC_invoke_finalizers();'
 
-
 class BoehmGcRuntimeTypeInfo_OpaqueNode(ContainerNode):
     nodekind = 'boehm rtti'
     globalcontainer = True

Modified: pypy/dist/pypy/translator/c/primitive.py
==============================================================================
--- pypy/dist/pypy/translator/c/primitive.py	(original)
+++ pypy/dist/pypy/translator/c/primitive.py	Wed May 17 01:01:11 2006
@@ -3,7 +3,7 @@
 from pypy.rpython.lltypesystem.lltype import *
 from pypy.rpython.lltypesystem.llmemory import Address, fakeaddress, \
      AddressOffset, ItemOffset, ArrayItemsOffset, FieldOffset, \
-     CompositeOffset, ArrayLengthOffset
+     CompositeOffset, ArrayLengthOffset, WeakGcAddress, fakeweakaddress
 from pypy.rpython.memory.gc import GCHeaderOffset
 from pypy.rpython.memory.lladdress import NULL
 from pypy.translator.c.support import cdecl
@@ -110,6 +110,12 @@
         
         return '(void*)(((char*)(%s)) + (%s))'%(base, db.get(value.offset))
 
+def name_weakgcaddress(value, db):
+    assert isinstance(value, fakeweakaddress)
+    assert value.ref is None # only weak NULL supported
+    return 'NULL'
+
+
 PrimitiveName = {
     Signed:   name_signed,
     SignedLongLong:   name_signedlonglong,
@@ -121,6 +127,7 @@
     Bool:     name_bool,
     Void:     name_void,
     Address:  name_address,
+    WeakGcAddress:  name_weakgcaddress,
     }
 
 PrimitiveType = {
@@ -134,6 +141,7 @@
     Bool:     'char @',
     Void:     'void @',
     Address:  'void* @',
+    WeakGcAddress:  'void* @',
     }
 
 PrimitiveErrorValue = {
@@ -147,6 +155,7 @@
     Bool:     '((char) -1)',
     Void:     '/* error */',
     Address:  'NULL',
+    WeakGcAddress:  'NULL',
     }
 
 def define_c_primitive(ll_type, c_name):

Modified: pypy/dist/pypy/translator/c/test/test_boehm.py
==============================================================================
--- pypy/dist/pypy/translator/c/test/test_boehm.py	(original)
+++ pypy/dist/pypy/translator/c/test/test_boehm.py	Wed May 17 01:01:11 2006
@@ -95,6 +95,37 @@
         # it might be the test's fault though.
         assert 0 < res <= 84
 
+    def test_weakgcaddress_is_weak(self):
+        from pypy.rpython.lltypesystem.lloperation import llop
+        from pypy.rpython.lltypesystem import lltype
+        from pypy.rpython.objectmodel import cast_object_to_weakgcaddress
+        class State:
+            pass
+        s = State()
+        class A(object):
+            def __del__(self):
+                s.a_dels += 1
+        def f(i=int):
+            if i:
+                s.a_dels = 0
+                a = A()
+                # this should not keep a alive
+                s.a = cast_object_to_weakgcaddress(a)
+            llop.gc__collect(lltype.Void)
+            llop.gc__collect(lltype.Void)
+            llop.gc__collect(lltype.Void)
+            return s.a_dels
+        fn = self.getcompiled(f)
+        # we can't demand that boehm has collected all of the objects,
+        # even with the gc__collect call.  calling the compiled
+        # function twice seems to help, though.
+        fn(1)
+        fn(0)
+        fn(0)
+        res = fn(0)
+        print res
+        assert res == 1
+
     def test_del_raises(self):
         from pypy.rpython.lltypesystem.lloperation import llop
         from pypy.rpython.lltypesystem import lltype

Modified: pypy/dist/pypy/translator/c/test/test_lladdresses.py
==============================================================================
--- pypy/dist/pypy/translator/c/test/test_lladdresses.py	(original)
+++ pypy/dist/pypy/translator/c/test/test_lladdresses.py	Wed May 17 01:01:11 2006
@@ -112,3 +112,20 @@
         return result
     fn = compile(f, [int])
     assert fn(1) == 2
+
+def test_weakaddress():
+    from pypy.rpython.objectmodel import cast_object_to_weakgcaddress
+    from pypy.rpython.objectmodel import cast_weakgcaddress_to_object
+    from pypy.rpython.lltypesystem.lloperation import llop
+    class A(object):
+        pass
+    def func(i):
+        l1 = []
+        l2 = []
+        for i in range(i):
+            a = A()
+            l1.append(a)
+            l2.append(cast_object_to_weakgcaddress(a))
+        return len(l1) == len(l2)
+    fn = compile(func, [int])
+    assert fn(10)

Modified: pypy/dist/pypy/translator/c/test/test_newgc.py
==============================================================================
--- pypy/dist/pypy/translator/c/test/test_newgc.py	(original)
+++ pypy/dist/pypy/translator/c/test/test_newgc.py	Wed May 17 01:01:11 2006
@@ -6,9 +6,9 @@
 from pypy.translator.translator import TranslationContext
 from pypy.translator.backendopt.stat import print_statistics
 from pypy.translator.c import genc, gc
-from pypy.rpython.lltypesystem import lltype
+from pypy.rpython.lltypesystem import lltype, llmemory
 from pypy.rpython.lltypesystem.lloperation import llop
-from pypy.rpython.objectmodel import cast_address_to_object, cast_object_to_address
+from pypy.rpython.objectmodel import cast_weakgcaddress_to_object, cast_object_to_weakgcaddress
 from pypy.rpython.memory.gctransform import GCTransformer
 
 from pypy import conftest
@@ -258,31 +258,54 @@
     __lifeline__ = None
 
 class Weakref(object):
-    def __init__(self, obj):
-        self.address = cast_object_to_address(obj)
+    def __init__(self, lifeline, index, obj, callback):
+        self.address = cast_object_to_weakgcaddress(obj)
+        self.callback = callback
+        self.lifeline_addr = cast_object_to_weakgcaddress(lifeline)
+        self.index = index
     
     def ref(self):
-        return cast_address_to_object(self.address, Weakrefable)
+        return cast_weakgcaddress_to_object(self.address, Weakrefable)
 
     def invalidate(self):
-        from pypy.rpython.lltypesystem.llmemory import NULL
-        self.address = NULL
+        self.address = llmemory.WEAKNULL
+        self.lifeline_addr = llmemory.WEAKNULL
+        if self.callback is not None:
+            self.callback(self)
+
+    def __del__(self):
+        if cast_weakgcaddress_to_object(self.address, Weakrefable) is not None:
+            lifeline = cast_weakgcaddress_to_object(self.lifeline_addr,
+                                                    WeakrefLifeline)
+            lifeline.ref_is_dead(self.index)
 
 class WeakrefLifeline(object):
     def __init__(self, obj):
-        self.ref = Weakref(obj)
+        self.refs = []
         
     def __del__(self):
-        self.ref.invalidate()
-    
-    def get_weakref(self):
-        return self.ref
+        i = 0
+        while i < len(self.refs):
+            addr_ref = self.refs[i]
+            if cast_weakgcaddress_to_object(addr_ref, Weakref) is not None:
+                ref = cast_weakgcaddress_to_object(addr_ref, Weakref)
+                ref.invalidate()
+            i += 1
+
+    def get_weakref(self, obj, callback):
+        ref = Weakref(self, len(self.refs), obj, callback)
+        addr_ref = cast_object_to_weakgcaddress(ref)
+        self.refs.append(addr_ref)
+        return ref
+
+    def ref_is_dead(self, index):
+        self.refs[index] = llmemory.WEAKNULL
 
-def get_weakref(obj):
+def get_weakref(obj, callback=None):
     assert isinstance(obj, Weakrefable)
     if obj.__lifeline__ is None:
         obj.__lifeline__ = WeakrefLifeline(obj)
-    return obj.__lifeline__.get_weakref()
+    return obj.__lifeline__.get_weakref(obj, callback)
 
 def test_weakref_alive():
     def func():
@@ -290,10 +313,10 @@
         f.x = 32
         ref1 = get_weakref(f)
         ref2 = get_weakref(f)
-        return f.x + ref2.ref().x + (ref1 is ref2)
-    assert func() == 65
+        return f.x + ref2.ref().x
+    assert func() == 64
     f = compile_func(func, [])
-    assert f() == 65
+    assert f() == 64
 
 def test_weakref_dying():
     def g():
@@ -307,6 +330,48 @@
     f = compile_func(func, [])
     assert f()
 
+def test_weakref_callback():
+    global_w = Weakrefable()
+    global_w.x = 31
+    def g(ref):
+        global_w.x = 32
+    def h():
+        f = Weakrefable()
+        f.x = 32
+        ref = get_weakref(f, g)
+        return ref
+    def func():
+        ref = h()
+        return (ref.ref() is None and ref.callback is not None and
+                global_w.x == 32)
+    assert func()
+    f = compile_func(func, [])
+    assert f()
+
+def test_weakref_dont_always_callback():
+    py.test.skip("in-progress")
+    global_w1 = Weakrefable()
+    global_w1.x = 30
+    global_w2 = Weakrefable()
+    global_w2.x = 30
+    def g1(ref):
+        global_w1.x = 32
+    def g2(ref):
+        global_w2.x = 32
+    def h():
+        f = Weakrefable()
+        f.x = 32
+        ref1 = get_weakref(f, g1)
+        ref2 = get_weakref(f, g2)
+        ref2 = None
+        return ref1
+    def func():
+        ref = h()
+        return global_w1.x == 32 and global_w2.x == 30
+    assert func()
+    f = compile_func(func, [])
+    assert f()
+
 # _______________________________________________________________
 # test framework
 


From cfbolz at codespeak.net  Wed May 17 01:07:45 2006
From: cfbolz at codespeak.net (cfbolz at codespeak.net)
Date: Wed, 17 May 2006 01:07:45 +0200 (CEST)
Subject: [pypy-svn] r27313 - pypy/dist/pypy/module/_weakref
Message-ID: <20060516230745.B7E93100A2@code0.codespeak.net>

Author: cfbolz
Date: Wed May 17 01:07:44 2006
New Revision: 27313

Modified:
   pypy/dist/pypy/module/_weakref/interp__weakref.py
Log:
typo


Modified: pypy/dist/pypy/module/_weakref/interp__weakref.py
==============================================================================
--- pypy/dist/pypy/module/_weakref/interp__weakref.py	(original)
+++ pypy/dist/pypy/module/_weakref/interp__weakref.py	Wed May 17 01:07:44 2006
@@ -21,6 +21,7 @@
                 w_ref = cast_weakgcaddress_to_object(addr_ref, W_Root)
                 w_ref.invalidate()
         for i in range(len(self.addr_refs) - 1, -1, -1):
+            addr_ref = self.addr_refs[i]
             if cast_weakgcaddress_to_object(addr_ref, W_Root) is not None:
                 w_ref = cast_weakgcaddress_to_object(addr_ref, W_Root)
                 w_ref.activate_callback()


From cfbolz at codespeak.net  Wed May 17 01:36:09 2006
From: cfbolz at codespeak.net (cfbolz at codespeak.net)
Date: Wed, 17 May 2006 01:36:09 +0200 (CEST)
Subject: [pypy-svn] r27316 - pypy/dist/pypy/translator/c/test
Message-ID: <20060516233609.07ED3100A8@code0.codespeak.net>

Author: cfbolz
Date: Wed May 17 01:36:06 2006
New Revision: 27316

Modified:
   pypy/dist/pypy/translator/c/test/test_newgc.py
Log:
fix test


Modified: pypy/dist/pypy/translator/c/test/test_newgc.py
==============================================================================
--- pypy/dist/pypy/translator/c/test/test_newgc.py	(original)
+++ pypy/dist/pypy/translator/c/test/test_newgc.py	Wed May 17 01:36:06 2006
@@ -274,9 +274,9 @@
             self.callback(self)
 
     def __del__(self):
-        if cast_weakgcaddress_to_object(self.address, Weakrefable) is not None:
-            lifeline = cast_weakgcaddress_to_object(self.lifeline_addr,
-                                                    WeakrefLifeline)
+        lifeline = cast_weakgcaddress_to_object(self.lifeline_addr,
+                                                WeakrefLifeline)
+        if lifeline is not None:
             lifeline.ref_is_dead(self.index)
 
 class WeakrefLifeline(object):
@@ -349,7 +349,6 @@
     assert f()
 
 def test_weakref_dont_always_callback():
-    py.test.skip("in-progress")
     global_w1 = Weakrefable()
     global_w1.x = 30
     global_w2 = Weakrefable()
@@ -363,7 +362,9 @@
         f.x = 32
         ref1 = get_weakref(f, g1)
         ref2 = get_weakref(f, g2)
-        ref2 = None
+        if f.x % 2 == 0: # start a new block to make sure ref2 dies before f
+            ref2 = None
+        f.x = 12
         return ref1
     def func():
         ref = h()


From antocuni at codespeak.net  Wed May 17 09:25:58 2006
From: antocuni at codespeak.net (antocuni at codespeak.net)
Date: Wed, 17 May 2006 09:25:58 +0200 (CEST)
Subject: [pypy-svn] r27324 - in pypy/dist/pypy: annotation rpython
	rpython/ootypesystem rpython/ootypesystem/test rpython/test
Message-ID: <20060517072558.5734E100AB@code0.codespeak.net>

Author: antocuni
Date: Wed May 17 09:25:53 2006
New Revision: 27324

Modified:
   pypy/dist/pypy/annotation/builtin.py
   pypy/dist/pypy/rpython/llinterp.py
   pypy/dist/pypy/rpython/ootypesystem/ootype.py
   pypy/dist/pypy/rpython/ootypesystem/rbuiltin.py
   pypy/dist/pypy/rpython/ootypesystem/rstr.py
   pypy/dist/pypy/rpython/ootypesystem/test/test_ooann.py
   pypy/dist/pypy/rpython/ootypesystem/test/test_oortype.py
   pypy/dist/pypy/rpython/test/test_rstr.py
Log:
Added support for string to integer conversion to ootypesystem.

Now ootypesystem string support should be complete! :-)



Modified: pypy/dist/pypy/annotation/builtin.py
==============================================================================
--- pypy/dist/pypy/annotation/builtin.py	(original)
+++ pypy/dist/pypy/annotation/builtin.py	Wed May 17 09:25:53 2006
@@ -526,6 +526,11 @@
     assert isinstance(base, SomeInteger)
     return SomeOOInstance(ootype.String)
 
+def ooparse_int(s, base):
+    assert isinstance(s, SomeOOInstance) and s.ootype is ootype.String
+    assert isinstance(base, SomeInteger)
+    return SomeInteger()
+
 BUILTIN_ANALYZERS[ootype.instanceof] = instanceof
 BUILTIN_ANALYZERS[ootype.new] = new
 BUILTIN_ANALYZERS[ootype.null] = null
@@ -534,6 +539,7 @@
 BUILTIN_ANALYZERS[ootype.subclassof] = subclassof
 BUILTIN_ANALYZERS[ootype.ooidentityhash] = ooidentityhash
 BUILTIN_ANALYZERS[ootype.oostring] = oostring
+BUILTIN_ANALYZERS[ootype.ooparse_int] = ooparse_int
 
 #________________________________
 # non-gc objects

Modified: pypy/dist/pypy/rpython/llinterp.py
==============================================================================
--- pypy/dist/pypy/rpython/llinterp.py	(original)
+++ pypy/dist/pypy/rpython/llinterp.py	Wed May 17 09:25:53 2006
@@ -1023,6 +1023,12 @@
     def op_oostring(self, obj, base):
         return ootype.oostring(obj, base)
 
+    def op_ooparse_int(self, s, base):
+        try:
+            return ootype.ooparse_int(s, base)
+        except ValueError:
+            self.make_llexception()
+
 class Tracer(object):
     Counter = 0
     file = None

Modified: pypy/dist/pypy/rpython/ootypesystem/ootype.py
==============================================================================
--- pypy/dist/pypy/rpython/ootypesystem/ootype.py	(original)
+++ pypy/dist/pypy/rpython/ootypesystem/ootype.py	Wed May 17 09:25:53 2006
@@ -1175,6 +1175,9 @@
         obj = '<%s object>' % obj._inst._TYPE._name
     return make_string(str(obj))
 
+def ooparse_int(s, base):
+    return int(s._str, base)
+
 def setItemType(LIST, ITEMTYPE):
     return LIST._set_itemtype(ITEMTYPE)
 

Modified: pypy/dist/pypy/rpython/ootypesystem/rbuiltin.py
==============================================================================
--- pypy/dist/pypy/rpython/ootypesystem/rbuiltin.py	(original)
+++ pypy/dist/pypy/rpython/ootypesystem/rbuiltin.py	Wed May 17 09:25:53 2006
@@ -65,6 +65,13 @@
     assert isinstance(hop.args_s[1], annmodel.SomeInteger)
     return hop.genop('oostring', hop.args_v, resulttype = ootype.String)
 
+def rtype_ooparse_int(hop):
+    assert isinstance(hop.args_s[0], annmodel.SomeOOInstance)\
+           and hop.args_s[0].ootype is ootype.String
+    assert isinstance(hop.args_s[1], annmodel.SomeInteger)
+    hop.has_implicit_exception(ValueError)
+    hop.exception_is_here()
+    return hop.genop('ooparse_int', hop.args_v, resulttype = ootype.Signed)
 
 BUILTIN_TYPER = {}
 BUILTIN_TYPER[ootype.new] = rtype_new
@@ -75,3 +82,4 @@
 BUILTIN_TYPER[ootype.ooidentityhash] = rtype_ooidentityhash
 BUILTIN_TYPER[isinstance] = rtype_builtin_isinstance
 BUILTIN_TYPER[ootype.oostring] = rtype_oostring
+BUILTIN_TYPER[ootype.ooparse_int] = rtype_ooparse_int

Modified: pypy/dist/pypy/rpython/ootypesystem/rstr.py
==============================================================================
--- pypy/dist/pypy/rpython/ootypesystem/rstr.py	(original)
+++ pypy/dist/pypy/rpython/ootypesystem/rstr.py	Wed May 17 09:25:53 2006
@@ -150,6 +150,9 @@
     def ll_split_chr(LIST, s, c):
         return s.ll_split_chr(c)
 
+    def ll_int(s, base):
+        return ootype.ooparse_int(s, base)
+
     def do_stringformat(cls, hop, sourcevarsrepr):
         InstanceRepr = hop.rtyper.type_system.rclass.InstanceRepr
         string_repr = hop.rtyper.type_system.rstr.string_repr

Modified: pypy/dist/pypy/rpython/ootypesystem/test/test_ooann.py
==============================================================================
--- pypy/dist/pypy/rpython/ootypesystem/test/test_ooann.py	(original)
+++ pypy/dist/pypy/rpython/ootypesystem/test/test_ooann.py	Wed May 17 09:25:53 2006
@@ -226,3 +226,11 @@
     a = RPythonAnnotator()
     s = a.build_types(oof, [])
     assert isinstance(s, annmodel.SomeBuiltin)
+
+def test_ooparse_int():
+    def oof(n, b):
+        return ooparse_int(oostring(n, b), b)
+
+    a = RPythonAnnotator()
+    s = a.build_types(oof, [int, int])
+    assert isinstance(s, annmodel.SomeInteger)

Modified: pypy/dist/pypy/rpython/ootypesystem/test/test_oortype.py
==============================================================================
--- pypy/dist/pypy/rpython/ootypesystem/test/test_oortype.py	(original)
+++ pypy/dist/pypy/rpython/ootypesystem/test/test_oortype.py	Wed May 17 09:25:53 2006
@@ -198,8 +198,11 @@
     assert interpret(oof, [s], type_system='ootype') == 3
 
 def test_oostring():
+    def const(c):
+        return c
+    
     def oof(ch):
-        return oostring(ch)
+        return oostring(ch, const(-1))
 
     ch = 'a'
     res = interpret(oof, [ch], type_system='ootype')
@@ -220,3 +223,11 @@
         assert b
 
     interpret(oof, [True], type_system='ootype')
+
+def test_ooparse_int():
+    def oof(n, b):
+        return ooparse_int(oostring(n, b), b)
+
+    for n in -42, 0, 42:
+        for b in 8, 10, 16:
+            assert interpret(oof, [n, b], type_system='ootype') == n

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	Wed May 17 09:25:53 2006
@@ -519,49 +519,49 @@
             s = s.replace('abb', 'c')
         raises (TyperError, interpret, fn, ())
 
-def test_int():
-    s1 = [ '42', '01001', 'abc', 'ABC', '4aBc', ' 12ef ', '+42', 'foo', '42foo', '42.1', '']
-    def fn(i, base):
-        s = s1[i]
-        res = int(s, base)
-        return res
-    for j in (10, 16, 2, 1, 36, 42, -3):
-        for i in range(len(s1)):
+    def test_int(self):
+        s1 = [ '42', '01001', 'abc', 'ABC', '4aBc', ' 12ef ', '+42', 'foo', '42foo', '42.1', '']
+        def fn(i, base):
+            s = s1[i]
+            res = int(s, base)
+            return res
+        for j in (10, 16, 2, 1, 36, 42, -3):
+            for i in range(len(s1)):
+                try:
+                    expected = fn(i, j)
+                except ValueError:
+                    self.interpret_raises(ValueError, fn, [i, j])
+                else:
+                    res = self.interpret(fn, [i, j])
+                    assert res == expected
+
+    def test_int_valueerror(self):
+        s1 = ['42g', '?']
+        def fn(i):
             try:
-                expected = fn(i, j)
+                return int(s1[i])
             except ValueError:
-                interpret_raises(ValueError, fn, [i, j])
-            else:
-                res = interpret(fn, [i, j])
-                assert res == expected
+                return -654
+        res = self.interpret(fn, [0])
+        assert res == -654
+        res = self.interpret(fn, [1])
+        assert res == -654
 
-def test_int_valueerror():
-    s1 = ['42g', '?']
-    def fn(i):
-        try:
-            return int(s1[i])
-        except ValueError:
-            return -654
-    res = interpret(fn, [0])
-    assert res == -654
-    res = interpret(fn, [1])
-    assert res == -654
-
-def test_char_mul_n():
-    def f(c, n):
-        return c*n
-    res = interpret(f, ['a', 4])
-    assert ''.join(res.chars) == 'a'*4
-    res = interpret(f, ['a', 0])
-    assert ''.join(res.chars) == ""
-    
-def test_n_mul_char():
-    def f(c, n):
-        return n*c
-    res = interpret(f, ['a', 4])
-    assert ''.join(res.chars) == 'a'*4
-    res = interpret(f, ['a', 0])
-    assert ''.join(res.chars) == ""
+    def test_char_mul_n(self):
+        def f(c, n):
+            return c*n
+        res = self.interpret(f, ['a', 4])
+        assert self.ll_to_string(res) == 'a'*4
+        res = self.interpret(f, ['a', 0])
+        assert self.ll_to_string(res) == ""
+
+    def test_n_mul_char(self):
+        def f(c, n):
+            return n*c
+        res = self.interpret(f, ['a', 4])
+        assert self.ll_to_string(res) == 'a'*4
+        res = self.interpret(f, ['a', 0])
+        assert self.ll_to_string(res) == ""
 
 def FIXME_test_str_to_pystringobj():
     def f(n):


From arigo at codespeak.net  Wed May 17 12:48:33 2006
From: arigo at codespeak.net (arigo at codespeak.net)
Date: Wed, 17 May 2006 12:48:33 +0200 (CEST)
Subject: [pypy-svn] r27340 - in pypy/dist/pypy: annotation rpython
	rpython/lltypesystem rpython/lltypesystem/test rpython/memory
	translator/c translator/llvm
Message-ID: <20060517104833.4A05210057@code0.codespeak.net>

Author: arigo
Date: Wed May 17 12:48:28 2006
New Revision: 27340

Added:
   pypy/dist/pypy/rpython/memory/gcheader.py   (contents, props changed)
Modified:
   pypy/dist/pypy/annotation/binaryop.py
   pypy/dist/pypy/annotation/bookkeeper.py
   pypy/dist/pypy/annotation/model.py
   pypy/dist/pypy/annotation/unaryop.py
   pypy/dist/pypy/rpython/lltypesystem/llmemory.py
   pypy/dist/pypy/rpython/lltypesystem/lltype.py
   pypy/dist/pypy/rpython/lltypesystem/test/test_llmemory.py
   pypy/dist/pypy/rpython/memory/gc.py
   pypy/dist/pypy/rpython/memory/gctransform.py
   pypy/dist/pypy/rpython/memory/lltypelayout.py
   pypy/dist/pypy/rpython/objectmodel.py
   pypy/dist/pypy/rpython/rbuiltin.py
   pypy/dist/pypy/rpython/rptr.py
   pypy/dist/pypy/translator/c/extfunc.py
   pypy/dist/pypy/translator/c/primitive.py
   pypy/dist/pypy/translator/llvm/extfunchelper.py
Log:
(arigo, some pedronis)

* added GCHeaderBuilder that contains the mappings between GcStructs
  and their GC headers.  In this way the mapping is not global but
  specific to the currently compiled GC.

* some fixes in the annotator to still propagate the constantness of
  Symbolics, without trying to constant-fold operations on them.

* general niceifications



Modified: pypy/dist/pypy/annotation/binaryop.py
==============================================================================
--- pypy/dist/pypy/annotation/binaryop.py	(original)
+++ pypy/dist/pypy/annotation/binaryop.py	Wed May 17 12:48:28 2006
@@ -60,7 +60,7 @@
                 result.knowntype = obj1.knowntype
             is_type_of1 = getattr(obj1, 'is_type_of', None)
             is_type_of2 = getattr(obj2, 'is_type_of', None)
-            if obj1.is_constant() and obj2.is_constant() and obj1.const == obj2.const:
+            if obj1.is_immutable_constant() and obj2.is_immutable_constant() and obj1.const == obj2.const:
                 result.const = obj1.const
                 is_type_of = {}
                 if is_type_of1:
@@ -269,7 +269,7 @@
     pow_ovf = _clone(pow, [ZeroDivisionError, OverflowError])
 
     def _compare_helper((int1, int2), opname, operation):
-        if int1.is_constant() and int2.is_constant():
+        if int1.is_immutable_constant() and int2.is_immutable_constant():
             r = immutablevalue(operation(int1.const, int2.const))
         else:
             r = SomeBool()
@@ -446,7 +446,7 @@
 class __extend__(pairtype(SomeTuple, SomeInteger)):
     
     def getitem((tup1, int2)):
-        if int2.is_constant():
+        if int2.is_immutable_constant():
             try:
                 return tup1.items[int2.const]
             except IndexError:
@@ -771,7 +771,7 @@
         pass
 
     def getitem((s_cto, s_index)):
-        if s_index.is_constant():
+        if s_index.is_immutable_constant():
             # check that the constant index is valid, just because we
             # are nice (users should really catch such errors by
             # testing their programs!)

Modified: pypy/dist/pypy/annotation/bookkeeper.py
==============================================================================
--- pypy/dist/pypy/annotation/bookkeeper.py	(original)
+++ pypy/dist/pypy/annotation/bookkeeper.py	Wed May 17 12:48:28 2006
@@ -307,7 +307,9 @@
             return SomeObject()
         tp = type(x)
         if issubclass(tp, Symbolic): # symbolic constants support
-            return x.annotation()
+            result = x.annotation()
+            result.const_box = Constant(x)
+            return result
         if tp is bool:
             result = SomeBool()
         elif tp is int:

Modified: pypy/dist/pypy/annotation/model.py
==============================================================================
--- pypy/dist/pypy/annotation/model.py	(original)
+++ pypy/dist/pypy/annotation/model.py	Wed May 17 12:48:28 2006
@@ -94,10 +94,21 @@
             TLS.no_side_effects_in_union -= 1
 
     def is_constant(self):
-        return hasattr(self, 'const')
+        d = self.__dict__
+        return 'const' in d or 'const_box' in d
 
     def is_immutable_constant(self):
-        return self.immutable and hasattr(self, 'const')
+        return self.immutable and 'const' in self.__dict__
+
+    # delegate accesses to 'const' to accesses to 'const_box.value',
+    # where const_box is a Constant.  XXX the idea is to eventually
+    # use systematically 'const_box' instead of 'const' for
+    # non-immutable constant annotations
+    class ConstAccessDelegator(object):
+        def __get__(self, obj, cls=None):
+            return obj.const_box.value
+    const = ConstAccessDelegator()
+    del ConstAccessDelegator
 
     # for debugging, record where each instance comes from
     # this is disabled if DEBUG is set to False

Modified: pypy/dist/pypy/annotation/unaryop.py
==============================================================================
--- pypy/dist/pypy/annotation/unaryop.py	(original)
+++ pypy/dist/pypy/annotation/unaryop.py	Wed May 17 12:48:28 2006
@@ -71,7 +71,7 @@
             return immutablevalue(bool(obj.const))
         else:
             s_len = obj.len()
-            if s_len.is_constant():
+            if s_len.is_immutable_constant():
                 return immutablevalue(s_len.const > 0)
             else:
                 return SomeBool()
@@ -188,7 +188,7 @@
     abs = neg
 
     def is_true(self):
-        if self.is_constant():
+        if self.is_immutable_constant():
             return getbookkeeper().immutablevalue(bool(self.const))
         return SomeBool()
 

Modified: pypy/dist/pypy/rpython/lltypesystem/llmemory.py
==============================================================================
--- pypy/dist/pypy/rpython/lltypesystem/llmemory.py	(original)
+++ pypy/dist/pypy/rpython/lltypesystem/llmemory.py	Wed May 17 12:48:28 2006
@@ -167,46 +167,46 @@
 
 
 class GCHeaderOffset(AddressOffset):
-    def __init__(self, minimal_layout):
-        self.minimal_layout = minimal_layout
+    def __init__(self, gcheaderbuilder):
+        self.gcheaderbuilder = gcheaderbuilder
 
     def __repr__(self):
         return '< GCHeaderOffset >'
 
     def __neg__(self):
-        return GCHeaderAntiOffset(self.minimal_layout)
+        return GCHeaderAntiOffset(self.gcheaderbuilder)
 
     def ref(self, headerref):
         header = headerref.get()
-        gcobj = _gc_header2struct[header._obj]
-        return _obref(lltype._ptr(lltype.Ptr(gcobj._TYPE), gcobj))
+        gcptr = self.gcheaderbuilder.object_from_header(header)
+        return _obref(gcptr)
 
     def raw_malloc(self, rest):
         assert rest
         if isinstance(rest[0], GCHeaderAntiOffset):
             return rest[1].raw_malloc(rest[2:])    # just for fun
         gcobjadr = rest[0].raw_malloc(rest[1:])
-        return gcobjadr - self
+        headerptr = self.gcheaderbuilder.new_header(gcobjadr.get())
+        return cast_ptr_to_adr(headerptr)
 
 
 class GCHeaderAntiOffset(AddressOffset):
-    def __init__(self, minimal_layout):
-        self.minimal_layout = minimal_layout
+    def __init__(self, gcheaderbuilder):
+        self.gcheaderbuilder = gcheaderbuilder
 
     def __repr__(self):
         return '< GCHeaderAntiOffset >'
 
     def __neg__(self):
-        return GCHeaderOffset(self.minimal_layout)
+        return GCHeaderOffset(self.gcheaderbuilder)
 
     def ref(self, gcptrref):
         gcptr = gcptrref.get()
-        headerobj = getgcheaderobj(self.minimal_layout, gcptr._obj)
-        p = lltype._ptr(lltype.Ptr(headerobj._TYPE), headerobj, True)
-        return _obref(p)
+        headerptr = self.gcheaderbuilder.header_of_object(gcptr)
+        return _obref(headerptr)
 
     def raw_malloc(self, rest):
-        assert rest
+        assert len(rest) >= 2
         assert isinstance(rest[0], GCHeaderOffset)
         return rest[1].raw_malloc(rest[2:])
 
@@ -493,28 +493,6 @@
 
 # ____________________________________________________________
 
-_gc_struct2header = weakref.WeakKeyDictionary()
-_gc_header2struct = weakref.WeakKeyDictionary()
-
-def getgcheaderobj(HDR, gcobj):
-    # XXX! this doesn't work if we use different HDRs in different tests
-    # for the same constants
-    try:
-        headerobj = _gc_struct2header[gcobj]
-    except KeyError:
-        # sanity checks
-        assert isinstance(gcobj._TYPE, lltype.GC_CONTAINER)
-        assert not isinstance(gcobj._TYPE, lltype.GcOpaqueType)
-        assert not gcobj._parentstructure()
-
-        headerobj = lltype.malloc(HDR, immortal=True)._obj
-        # make uninitialized access explode
-        for fldname in HDR._names:
-            getattr(type(headerobj), fldname).__set__(headerobj, None)
-        _gc_struct2header[gcobj] = headerobj
-        _gc_header2struct[headerobj] = gcobj
-    return headerobj
-
 def raw_malloc(size):
     if not isinstance(size, AddressOffset):
         raise NotImplementedError(size)

Modified: pypy/dist/pypy/rpython/lltypesystem/lltype.py
==============================================================================
--- pypy/dist/pypy/rpython/lltypesystem/lltype.py	(original)
+++ pypy/dist/pypy/rpython/lltypesystem/lltype.py	Wed May 17 12:48:28 2006
@@ -782,7 +782,7 @@
     # If p is a pointer, returns the same pointer casted to the largest
     # containing structure (for the cast where p points to the header part).
     # Also un-hides pointers to opaque.  Null pointers become None.
-    assert not isinstance(p, _parentable)  # pointer or primitive
+    assert not isinstance(p, _container)  # pointer or primitive
     T = typeOf(p)
     if not isinstance(T, Ptr):
         return p      # primitive
@@ -1054,9 +1054,25 @@
             # normal case
             return llmemory.fakeaddress(normalizeptr(self))
 
+    def _as_ptr(self):
+        return self
+    def _as_obj(self):
+        return self._obj
+
 assert not '__dict__' in dir(_ptr)
 
-class _parentable(object):
+class _container(object):
+    __slots__ = ()
+    def _parentstructure(self):
+        return None
+    def _check(self):
+        pass
+    def _as_ptr(self):
+        return _ptr(Ptr(self._TYPE), self, True)
+    def _as_obj(self):
+        return self
+
+class _parentable(_container):
     _kind = "?"
 
     __slots__ = ('_TYPE',
@@ -1315,19 +1331,13 @@
     _makeptr = staticmethod(_makeptr)
 
 
-class _func(object):
+class _func(_container):
     def __init__(self, TYPE, **attrs):
         self._TYPE = TYPE
         self._name = "?"
         self._callable = None
         self.__dict__.update(attrs)
 
-    def _parentstructure(self):
-        return None
-
-    def _check(self):
-        pass
-
     def __repr__(self):
         return '<%s>' % (self,)
 
@@ -1372,17 +1382,11 @@
         return "%s %s" % (self._TYPE.__name__, self._name)
 
 
-class _pyobject(Hashable):
+class _pyobject(Hashable, _container):
     __slots__ = []   # or we get in trouble with pickling
 
     _TYPE = PyObject
 
-    def _parentstructure(self):
-        return None
-
-    def _check(self):
-        pass
-
     def __repr__(self):
         return '<%s>' % (self,)
 

Modified: pypy/dist/pypy/rpython/lltypesystem/test/test_llmemory.py
==============================================================================
--- pypy/dist/pypy/rpython/lltypesystem/test/test_llmemory.py	(original)
+++ pypy/dist/pypy/rpython/lltypesystem/test/test_llmemory.py	Wed May 17 12:48:28 2006
@@ -258,9 +258,10 @@
     py.test.raises(IndexError, "item_adr.signed[0]")
 
 def test_raw_malloc_gcstruct():
-    from pypy.rpython.memory import gc
+    from pypy.rpython.memory import gcheader
     HDR = lltype.Struct('header', ('a', lltype.Signed))
-    gchdr = gc.GCHeaderOffset(HDR)
+    builder = gcheader.GCHeaderBuilder(HDR)
+    gchdr = builder.size_gc_header
     S = lltype.GcStruct('S', ('x', lltype.Signed))
 
     def allocate():

Modified: pypy/dist/pypy/rpython/memory/gc.py
==============================================================================
--- pypy/dist/pypy/rpython/memory/gc.py	(original)
+++ pypy/dist/pypy/rpython/memory/gc.py	Wed May 17 12:48:28 2006
@@ -1,6 +1,7 @@
 from pypy.rpython.memory.lladdress import raw_malloc, raw_free, raw_memcopy
 from pypy.rpython.memory.lladdress import NULL, _address, raw_malloc_usage
 from pypy.rpython.memory.support import get_address_linked_list
+from pypy.rpython.memory.gcheader import GCHeaderBuilder
 from pypy.rpython.memory import lltypesimulation
 from pypy.rpython.lltypesystem import lltype, llmemory
 from pypy.rpython.objectmodel import free_non_gc_object
@@ -9,11 +10,7 @@
 import sys
 
 int_size = lltypesimulation.sizeof(lltype.Signed)
-
-GCHeaderOffset = llmemory.GCHeaderOffset
-
-gc_header_two_ints = GCHeaderOffset(
-    lltype.Struct("header", ("a", lltype.Signed), ("b", lltype.Signed)))
+gc_header_two_ints = 2*int_size
 
 class GCError(Exception):
     pass
@@ -109,7 +106,6 @@
 
     HDR = lltype.Struct('header', ('typeid', lltype.Signed))
     HDRPTR = lltype.Ptr(HDR)
-    _size_gc_header = GCHeaderOffset(HDR)
 
     def __init__(self, AddressLinkedList, start_heap_size=4096, get_roots=None):
         self.heap_usage = 0          # at the end of the latest collection
@@ -122,6 +118,7 @@
         self.AddressLinkedList = AddressLinkedList
         #self.set_query_functions(None, None, None, None, None, None, None)
         self.get_roots = get_roots
+        self.gcheaderbuilder = GCHeaderBuilder(self.HDR)
 
     def setup(self):
         self.malloced_objects = self.AddressLinkedList()
@@ -142,7 +139,7 @@
     def malloc_fixedsize(self, typeid, size, can_collect):
         if can_collect and self.bytes_malloced > self.bytes_malloced_threshold:
             self.collect()
-        size_gc_header = MarkSweepGC._size_gc_header
+        size_gc_header = self.gcheaderbuilder.size_gc_header
         result = raw_malloc(size_gc_header + size)
         hdr = llmemory.cast_adr_to_ptr(result, self.HDRPTR)
         hdr.typeid = typeid << 1
@@ -161,7 +158,7 @@
             raise MemoryError
         # XXX also check for overflow on the various '+' below!
         size += varsize
-        size_gc_header = MarkSweepGC._size_gc_header
+        size_gc_header = self.gcheaderbuilder.size_gc_header
         result = raw_malloc(size_gc_header + size)
         (result + size_gc_header + offset_to_length).signed[0] = length
         hdr = llmemory.cast_adr_to_ptr(result, self.HDRPTR)
@@ -176,6 +173,7 @@
         os.write(2, 'collecting...\n')
         start_time = time.time()
         roots = self.get_roots()
+        size_gc_header = self.gcheaderbuilder.size_gc_header
         objects = self.AddressLinkedList()
         while 1:
             curr = roots.pop()
@@ -186,7 +184,7 @@
             objects.append(curr.address[0])
             # the last sweep did not clear the mark bit of static roots, 
             # since they are not in the malloced_objects list
-            gc_info = curr.address[0] - MarkSweepGC._size_gc_header
+            gc_info = curr.address[0] - size_gc_header
             hdr = llmemory.cast_adr_to_ptr(gc_info, self.HDRPTR)
             hdr.typeid = hdr.typeid & (~1)
         free_non_gc_object(roots)
@@ -198,7 +196,7 @@
 ##             print "object: ", curr
             if curr == NULL:
                 break
-            gc_info = curr - MarkSweepGC._size_gc_header
+            gc_info = curr - size_gc_header
             hdr = llmemory.cast_adr_to_ptr(gc_info, self.HDRPTR)
             if hdr.typeid & 1:
                 continue
@@ -237,9 +235,9 @@
             typeid = hdr.typeid >> 1
             size = self.fixed_size(typeid)
             if self.is_varsize(typeid):
-                length = (curr + MarkSweepGC._size_gc_header + self.varsize_offset_to_length(typeid)).signed[0]
+                length = (curr + size_gc_header + self.varsize_offset_to_length(typeid)).signed[0]
                 size += self.varsize_item_sizes(typeid) * length
-            estimate = raw_malloc_usage(MarkSweepGC._size_gc_header + size)
+            estimate = raw_malloc_usage(size_gc_header + size)
             if hdr.typeid & 1:
                 hdr.typeid = hdr.typeid & (~1)
                 newmo.append(curr)
@@ -274,7 +272,7 @@
         return self.heap_usage, self.bytes_malloced
 
     def size_gc_header(self, typeid=0):
-        return MarkSweepGC._size_gc_header
+        return self.gcheaderbuilder.size_gc_header
 
     def init_gc_object(self, addr, typeid):
         hdr = llmemory.cast_adr_to_ptr(addr, self.HDRPTR)

Added: pypy/dist/pypy/rpython/memory/gcheader.py
==============================================================================
--- (empty file)
+++ pypy/dist/pypy/rpython/memory/gcheader.py	Wed May 17 12:48:28 2006
@@ -0,0 +1,35 @@
+import weakref
+from pypy.rpython.lltypesystem import lltype, llmemory
+
+
+class GCHeaderBuilder(object):
+
+    def __init__(self, HDR):
+        self.HDR = HDR
+        self.obj2header = weakref.WeakKeyDictionary()
+        self.header2obj = weakref.WeakKeyDictionary()
+        self.size_gc_header = llmemory.GCHeaderOffset(self)
+
+    def header_of_object(self, gcptr):
+        return self.obj2header[gcptr._as_obj()]
+
+    def object_from_header(self, headerptr):
+        return self.header2obj[headerptr._as_obj()]
+
+    def get_header(self, gcptr):
+        return self.obj2header.get(gcptr._as_obj(), None)
+
+    def new_header(self, gcptr):
+        gcobj = gcptr._as_obj()
+        assert gcobj not in self.obj2header
+        # sanity checks
+        assert isinstance(gcobj._TYPE, lltype.GC_CONTAINER)
+        assert not isinstance(gcobj._TYPE, lltype.GcOpaqueType)
+        assert not gcobj._parentstructure()
+        headerptr = lltype.malloc(self.HDR, immortal=True)
+        self.obj2header[gcobj] = headerptr
+        self.header2obj[headerptr._obj] = gcptr._as_ptr()
+        return headerptr
+
+    def _freeze_(self):
+        return True     # for reads of size_gc_header

Modified: pypy/dist/pypy/rpython/memory/gctransform.py
==============================================================================
--- pypy/dist/pypy/rpython/memory/gctransform.py	(original)
+++ pypy/dist/pypy/rpython/memory/gctransform.py	Wed May 17 12:48:28 2006
@@ -14,6 +14,7 @@
 from pypy.annotation import model as annmodel
 from pypy.rpython import rmodel, rptr, annlowlevel, typesystem
 from pypy.rpython.memory import gc, lladdress
+from pypy.rpython.memory.gcheader import GCHeaderBuilder
 from pypy.rpython.annlowlevel import MixLevelHelperAnnotator
 from pypy.rpython.extregistry import ExtRegistryEntry
 import sets, os
@@ -388,19 +389,21 @@
 
 class RefcountingGCTransformer(GCTransformer):
 
-    gc_header_offset = gc.GCHeaderOffset(lltype.Struct("header", ("refcount", lltype.Signed)))
+    HDR = lltype.Struct("header", ("refcount", lltype.Signed))
 
     def __init__(self, translator):
         super(RefcountingGCTransformer, self).__init__(translator)
+        self.gcheaderbuilder = GCHeaderBuilder(self.HDR)
+        gc_header_offset = self.gcheaderbuilder.size_gc_header
         self.deallocator_graphs_needing_transforming = []
         # create incref graph
         def ll_incref(adr):
             if adr:
-                gcheader = adr - RefcountingGCTransformer.gc_header_offset
+                gcheader = adr - gc_header_offset
                 gcheader.signed[0] = gcheader.signed[0] + 1
         def ll_decref(adr, dealloc):
             if adr:
-                gcheader = adr - RefcountingGCTransformer.gc_header_offset
+                gcheader = adr - gc_header_offset
                 refcount = gcheader.signed[0] - 1
                 gcheader.signed[0] = refcount
                 if refcount == 0:
@@ -490,6 +493,13 @@
     def finish(self):
         super(RefcountingGCTransformer, self).finish()
 
+##    -- maybe add this for tests and for consistency --
+##    def consider_constant(self, TYPE, value):
+##        p = value._as_ptr()
+##        if not self.gcheaderbuilder.get_header(p):
+##            hdr = new_header(p)
+##            hdr.refcount = sys.maxint // 2
+
     def static_deallocation_funcptr_for_type(self, TYPE):
         if TYPE in self.static_deallocator_funcptrs:
             return self.static_deallocator_funcptrs[TYPE]
@@ -543,7 +553,7 @@
              'llop': llop,
              'lltype': lltype,
              'destrptr': destrptr,
-             'gc_header_offset': RefcountingGCTransformer.gc_header_offset,
+             'gc_header_offset': self.gcheaderbuilder.size_gc_header,
              'cast_adr_to_ptr': llmemory.cast_adr_to_ptr,
              'cast_pointer': lltype.cast_pointer,
              'PTR_TYPE': lltype.Ptr(TYPE),
@@ -577,9 +587,10 @@
         
         RTTI_PTR = lltype.Ptr(lltype.RuntimeTypeInfo)
         QUERY_ARG_TYPE = lltype.typeOf(queryptr).TO.ARGS[0]
+        gc_header_offset = self.gcheaderbuilder.size_gc_header
         def ll_dealloc(addr):
             # bump refcount to 1
-            gcheader = addr - RefcountingGCTransformer.gc_header_offset
+            gcheader = addr - gc_header_offset
             gcheader.signed[0] = 1
             v = llmemory.cast_adr_to_ptr(addr, QUERY_ARG_TYPE)
             rtti = queryptr(v)
@@ -631,8 +642,6 @@
 
 
 class BoehmGCTransformer(GCTransformer):
-    gc_header_offset = gc.GCHeaderOffset(lltype.Void)
-
     def __init__(self, translator, inline=False):
         super(BoehmGCTransformer, self).__init__(translator, inline=inline)
         self.finalizer_funcptrs = {}
@@ -908,8 +917,7 @@
         r_gc = self.translator.rtyper.getrepr(s_gc)
         self.c_const_gc = rmodel.inputconst(r_gc, self.gcdata.gc)
 
-        self.gc_header_offset = self.gcdata.gc.size_gc_header()
-        HDR = self._gc_HDR = self.gc_header_offset.minimal_layout
+        HDR = self._gc_HDR = self.gcdata.gc.gcheaderbuilder.HDR
         self._gc_fields = fields = []
         for fldname in HDR._names:
             FLDTYPE = getattr(HDR, fldname)
@@ -1012,15 +1020,17 @@
         if id(value) in self.seen_roots:
             return
         self.seen_roots[id(value)] = True
-        p = lltype._ptr(lltype.Ptr(TYPE), value)
-        adr = llmemory.cast_ptr_to_adr(p)
 
         if isinstance(TYPE, (lltype.GcStruct, lltype.GcArray)):
             typeid = self.get_type_id(TYPE)
             if lltype.top_container(value) is value:
-                self.gcdata.gc.init_gc_object(adr-self.gc_header_offset, typeid)
+                hdrbuilder = self.gcdata.gc.gcheaderbuilder
+                hdr = hdrbuilder.new_header(value)
+                adr = llmemory.cast_ptr_to_adr(hdr)
+                self.gcdata.gc.init_gc_object(adr, typeid)
 
         if TYPE != lltype.PyObject and find_gc_ptrs_in_type(TYPE):
+            adr = llmemory.cast_ptr_to_adr(value._as_ptr())
             if isinstance(TYPE, (lltype.GcStruct, lltype.GcArray)):
                 self.static_gc_roots.append(adr)
             else: 
@@ -1031,12 +1041,9 @@
         return self._gc_fields
 
     def gc_field_values_for(self, obj):
-        p = lltype._ptr(lltype.Ptr(lltype.typeOf(obj)), obj)
-        adr = llmemory.cast_ptr_to_adr(p)
+        hdr = self.gcdata.gc.gcheaderbuilder.header_of_object(obj)
         HDR = self._gc_HDR
-        p_hdr = llmemory.cast_adr_to_ptr(adr-self.gc_header_offset,
-                                         lltype.Ptr(HDR))
-        return [getattr(p_hdr, fldname) for fldname in HDR._names]
+        return [getattr(hdr, fldname) for fldname in HDR._names]
 
     def offsets2table(self, offsets, TYPE):
         try:

Modified: pypy/dist/pypy/rpython/memory/lltypelayout.py
==============================================================================
--- pypy/dist/pypy/rpython/memory/lltypelayout.py	(original)
+++ pypy/dist/pypy/rpython/memory/lltypelayout.py	Wed May 17 12:48:28 2006
@@ -90,7 +90,6 @@
         return fixedsize + i * varsize
 
 def convert_offset_to_int(offset):
-    from pypy.rpython.memory.gc import GCHeaderOffset
     if isinstance(offset, llmemory.FieldOffset):
         layout = get_layout(offset.TYPE)
         return layout[offset.fldname]
@@ -102,8 +101,8 @@
         return sizeof(offset.TYPE) * offset.repeat
     elif isinstance(offset, llmemory.ArrayItemsOffset):
         return get_fixed_size(lltype.Signed)
-    elif isinstance(offset, GCHeaderOffset):
-        return sizeof(offset.minimal_layout)
+    elif isinstance(offset, llmemory.GCHeaderOffset):
+        return sizeof(offset.gcheaderbuilder.HDR)
     else:
         raise Exception("unknown offset type %r"%offset)
         

Modified: pypy/dist/pypy/rpython/objectmodel.py
==============================================================================
--- pypy/dist/pypy/rpython/objectmodel.py	(original)
+++ pypy/dist/pypy/rpython/objectmodel.py	Wed May 17 12:48:28 2006
@@ -14,7 +14,10 @@
         return None
 
     def __cmp__(self, other):
-        raise TypeError("Symbolics can not be compared!")
+        if self is other:
+            return 0
+        else:
+            raise TypeError("Symbolics can not be compared!")
 
     def __hash__(self):
         raise TypeError("Symbolics are not hashable!")

Modified: pypy/dist/pypy/rpython/rbuiltin.py
==============================================================================
--- pypy/dist/pypy/rpython/rbuiltin.py	(original)
+++ pypy/dist/pypy/rpython/rbuiltin.py	Wed May 17 12:48:28 2006
@@ -427,7 +427,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(lltype.Ptr(lltype.RuntimeTypeInfo)))
+                     resulttype = hop.r_result.lowleveltype)
 
 BUILTIN_TYPER[lltype.malloc] = rtype_malloc
 BUILTIN_TYPER[lltype.free] = rtype_free

Modified: pypy/dist/pypy/rpython/rptr.py
==============================================================================
--- pypy/dist/pypy/rpython/rptr.py	(original)
+++ pypy/dist/pypy/rpython/rptr.py	Wed May 17 12:48:28 2006
@@ -149,16 +149,16 @@
 class LLADTMethRepr(Repr):
 
     def __init__(self, adtmeth):
-        self.adtmeth = adtmeth
+        self.func = adtmeth.func
         self.lowleveltype = adtmeth.ll_ptrtype
 
     def rtype_simple_call(self, hop):
         hop2 = hop.copy()
-        func = self.adtmeth.func
+        func = self.func
         s_func = hop.rtyper.annotator.bookkeeper.immutablevalue(func)
         v_ptr = hop2.args_v[0]
         hop2.r_s_popfirstarg()
-        hop2.v_s_insertfirstarg(v_ptr, annmodel.SomePtr(self.adtmeth.ll_ptrtype))
+        hop2.v_s_insertfirstarg(v_ptr, annmodel.SomePtr(self.lowleveltype))
         hop2.v_s_insertfirstarg(flowmodel.Constant(func), s_func)
         return hop2.dispatch()
 

Modified: pypy/dist/pypy/translator/c/extfunc.py
==============================================================================
--- pypy/dist/pypy/translator/c/extfunc.py	(original)
+++ pypy/dist/pypy/translator/c/extfunc.py	Wed May 17 12:48:28 2006
@@ -159,7 +159,7 @@
         if modname not in modules:
             modules[modname] = True
             yield 'LL_NEED_%s' % modname.upper(), 1
-        funcptr = lltype._ptr(lltype.Ptr(lltype.typeOf(funcobj)), funcobj) # hum
+        funcptr = funcobj._as_ptr()
         yield c_name, funcptr
 
 def predeclare_exception_data(db, rtyper, optimize=True):

Modified: pypy/dist/pypy/translator/c/primitive.py
==============================================================================
--- pypy/dist/pypy/translator/c/primitive.py	(original)
+++ pypy/dist/pypy/translator/c/primitive.py	Wed May 17 12:48:28 2006
@@ -3,8 +3,8 @@
 from pypy.rpython.lltypesystem.lltype import *
 from pypy.rpython.lltypesystem.llmemory import Address, fakeaddress, \
      AddressOffset, ItemOffset, ArrayItemsOffset, FieldOffset, \
-     CompositeOffset, ArrayLengthOffset, WeakGcAddress, fakeweakaddress
-from pypy.rpython.memory.gc import GCHeaderOffset
+     CompositeOffset, ArrayLengthOffset, WeakGcAddress, fakeweakaddress, \
+     GCHeaderOffset
 from pypy.rpython.memory.lladdress import NULL
 from pypy.translator.c.support import cdecl
 

Modified: pypy/dist/pypy/translator/llvm/extfunchelper.py
==============================================================================
--- pypy/dist/pypy/translator/llvm/extfunchelper.py	(original)
+++ pypy/dist/pypy/translator/llvm/extfunchelper.py	Wed May 17 12:48:28 2006
@@ -182,7 +182,7 @@
         if modname not in modules:
             modules[modname] = True
             yield 'LL_NEED_%s' % modname.upper(), 1
-        funcptr = lltype._ptr(lltype.Ptr(lltype.typeOf(funcobj)), funcobj) # hum
+        funcptr = funcobj._as_ptr()
         yield c_name, funcptr
 
 def predeclare_exception_data(db, rtyper, optimize=True):


From arigo at codespeak.net  Wed May 17 13:21:53 2006
From: arigo at codespeak.net (arigo at codespeak.net)
Date: Wed, 17 May 2006 13:21:53 +0200 (CEST)
Subject: [pypy-svn] r27344 - in pypy/dist/pypy/rpython/memory: . test
Message-ID: <20060517112153.DC86510063@code0.codespeak.net>

Author: arigo
Date: Wed May 17 13:21:52 2006
New Revision: 27344

Modified:
   pypy/dist/pypy/rpython/memory/gc.py
   pypy/dist/pypy/rpython/memory/support.py
   pypy/dist/pypy/rpython/memory/test/test_support.py
Log:
Leak!  One chunk per AddressLinkedList was never freed.


Modified: pypy/dist/pypy/rpython/memory/gc.py
==============================================================================
--- pypy/dist/pypy/rpython/memory/gc.py	(original)
+++ pypy/dist/pypy/rpython/memory/gc.py	Wed May 17 13:21:52 2006
@@ -223,7 +223,7 @@
                         j += 1
                     i += 1
             hdr.typeid = hdr.typeid | 1
-        free_non_gc_object(objects)
+        objects.delete()
         newmo = self.AddressLinkedList()
         curr_heap_size = 0
         freed_size = 0
@@ -245,7 +245,7 @@
             else:
                 freed_size += estimate
                 raw_free(curr)
-        free_non_gc_object(self.malloced_objects)
+        self.malloced_objects.delete()
         self.malloced_objects = newmo
         if curr_heap_size > self.bytes_malloced_threshold:
             self.bytes_malloced_threshold = curr_heap_size
@@ -483,7 +483,7 @@
             typeid = (deallocate - self.size_gc_header()).signed[1]
             (deallocate - self.size_gc_header()).signed[1] = -typeid - 1
             self.deallocate(deallocate)
-        free_non_gc_object(dealloc_list)
+        dealloc_list.delete()
         while 1:
             root = roots.pop()
             if root == NULL:

Modified: pypy/dist/pypy/rpython/memory/support.py
==============================================================================
--- pypy/dist/pypy/rpython/memory/support.py	(original)
+++ pypy/dist/pypy/rpython/memory/support.py	Wed May 17 13:21:52 2006
@@ -1,5 +1,6 @@
 from pypy.rpython.lltypesystem import lltype, llmemory
 from pypy.rpython.memory.lltypelayout import sizeof
+from pypy.rpython.objectmodel import free_non_gc_object
 
 INT_SIZE = sizeof(lltype.Signed)
 
@@ -69,13 +70,12 @@
             self.chunk.length = used_chunks - 1
             return result
 
-        def free(self):   # XXX very inefficient
+        def delete(self):
             cur = self.chunk
-            while cur.previous:
+            while cur:
                 prev = cur.previous
                 unused_chunks.put(cur)
                 cur = prev
-            self.chunk = cur
-            cur.length =  0
+            free_non_gc_object(self)
 
     return AddressLinkedList

Modified: pypy/dist/pypy/rpython/memory/test/test_support.py
==============================================================================
--- pypy/dist/pypy/rpython/memory/test/test_support.py	(original)
+++ pypy/dist/pypy/rpython/memory/test/test_support.py	Wed May 17 13:21:52 2006
@@ -22,14 +22,12 @@
         assert ll.pop() == NULL
         assert ll.pop() == NULL
         ll.append(addr)
-        ll.free()
-        free_non_gc_object(ll)
+        ll.delete()
         ll = AddressLinkedList()
         ll.append(addr)
         ll.append(addr + 1)
         ll.append(addr + 2)
-        ll.free()
-        free_non_gc_object(ll)
+        ll.delete()
         raw_free(addr)
 
     def test_big_access(self):
@@ -49,8 +47,7 @@
         for i in range(3000)[::-1]:
             a = ll.pop()
             assert a - addr == i
-        ll.free()
-        free_non_gc_object(ll)
+        ll.delete()
         raw_free(addr)
         
 def test_linked_list_annotate():
@@ -81,14 +78,12 @@
         for i in range(299, -1, -1):
             a = ll.pop()
             res = res and (a - INT_SIZE*i == addr)
-        ll.free()
-        free_non_gc_object(ll)
+        ll.delete()
         ll = AddressLinkedList()
         ll.append(addr)
         ll.append(addr + INT_SIZE*1)
         ll.append(addr + INT_SIZE*2)
-        ll.free()
-        free_non_gc_object(ll)
+        ll.delete()
         raw_free(addr)
         return res
 


From antocuni at codespeak.net  Wed May 17 14:10:04 2006
From: antocuni at codespeak.net (antocuni at codespeak.net)
Date: Wed, 17 May 2006 14:10:04 +0200 (CEST)
Subject: [pypy-svn] r27350 - in pypy/dist/pypy/rpython: ootypesystem test
Message-ID: <20060517121004.5C48010063@code0.codespeak.net>

Author: antocuni
Date: Wed May 17 14:09:58 2006
New Revision: 27350

Modified:
   pypy/dist/pypy/rpython/ootypesystem/rlist.py
   pypy/dist/pypy/rpython/test/test_rlist.py
Log:
Add support for list to string conversion to ootypesystem.



Modified: pypy/dist/pypy/rpython/ootypesystem/rlist.py
==============================================================================
--- pypy/dist/pypy/rpython/ootypesystem/rlist.py	(original)
+++ pypy/dist/pypy/rpython/ootypesystem/rlist.py	Wed May 17 14:09:58 2006
@@ -7,6 +7,7 @@
 from pypy.rpython.ootypesystem import ootype
 from pypy.rpython.ootypesystem.rslice import SliceRepr, \
      startstop_slice_repr, startonly_slice_repr, minusone_slice_repr
+from pypy.rpython.ootypesystem import rstr
 
 
 class BaseListRepr(AbstractBaseListRepr):
@@ -54,6 +55,25 @@
     def make_iterator_repr(self):
         return ListIteratorRepr(self)
 
+    def ll_str(self, lst):
+        item_repr = self.item_repr
+        length = lst.ll_length()        
+        buf = ootype.new(ootype.StringBuilder)
+        buf.ll_append_char('[')
+        i = 0
+        while i < length-1:
+            item = lst.ll_getitem_fast(i)
+            buf.ll_append(item_repr.ll_str(item))
+            buf.ll_append_char(',')
+            buf.ll_append_char(' ')
+            i += 1
+        if length > 0:
+            lastitem = lst.ll_getitem_fast(i)
+            buf.ll_append(item_repr.ll_str(lastitem))
+        buf.ll_append_char(']')
+        return buf.ll_build()
+
+
 class ListRepr(AbstractListRepr, BaseListRepr):
 
     pass

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	Wed May 17 14:09:58 2006
@@ -622,7 +622,6 @@
 
 
     def test_list_comparestr(self):
-        self._skip_oo('strings')
         def fn(i, j, neg=False):
             s1 = [["hell"], ["hello", "world"]]
             s1[0][0] += "o" # ensure no interning
@@ -701,7 +700,6 @@
 
 
     def test_not_a_char_list_after_all(self):
-        self._skip_oo('strings')
         def fn():
             l = ['h', 'e', 'l', 'l', 'o']
             return 'world' in l
@@ -746,18 +744,18 @@
 
 
     def test_list_str(self):
-        self._skip_oo('strings')
+        self._skip_oo('int to string')
         def fn():
             return str([1,2,3])
 
         res = self.interpret(fn, [])
-        assert ''.join(res.chars) == fn()
+        assert self.ll_to_string(res) == fn()
 
         def fn():
             return str([[1,2,3]])
 
         res = self.interpret(fn, [])
-        assert ''.join(res.chars) == fn()
+        assert self.ll_to_string(res) == fn()
 
         def fn():
             l = [1,2]
@@ -765,7 +763,7 @@
             return str(l)
 
         res = self.interpret(fn, [])
-        assert ''.join(res.chars) == fn()
+        assert self.ll_to_string(res) == fn()
 
         def fn():
             l = [1,2]
@@ -773,7 +771,7 @@
             return str([l])
 
         res = self.interpret(fn, [])
-        assert ''.join(res.chars) == fn()
+        assert self.ll_to_string(res) == fn()
 
     def test_list_or_None(self):
         empty_list = []
@@ -1138,6 +1136,9 @@
     def ll_to_list(self, l):
         return map(None, l.ll_items())[:l.ll_length()]
 
+    def ll_to_string(self, s):
+        return ''.join(s.chars)
+
     def class_name(self, value):
         return "".join(value.super.typeptr.name)[:-1]
 
@@ -1161,5 +1162,8 @@
     def ll_to_list(self, l):
         return l._list[:]
 
+    def ll_to_string(self, s):
+        return s._str
+
     def class_name(self, value):
         return ootype.dynamicType(value)._name.split(".")[-1] 


From ericvrp at codespeak.net  Wed May 17 14:36:22 2006
From: ericvrp at codespeak.net (ericvrp at codespeak.net)
Date: Wed, 17 May 2006 14:36:22 +0200 (CEST)
Subject: [pypy-svn] r27357 - in pypy/dist/pypy/translator/llvm: . externs
	externs/test module pyllvm/test test wrapable/test
Message-ID: <20060517123622.465F710063@code0.codespeak.net>

Author: ericvrp
Date: Wed May 17 14:36:16 2006
New Revision: 27357

Modified:
   pypy/dist/pypy/translator/llvm/buildllvm.py
   pypy/dist/pypy/translator/llvm/database.py
   pypy/dist/pypy/translator/llvm/exception.py
   pypy/dist/pypy/translator/llvm/externs/ringbuffer.py
   pypy/dist/pypy/translator/llvm/externs/test/test_ringbuffer.py
   pypy/dist/pypy/translator/llvm/funcnode.py
   pypy/dist/pypy/translator/llvm/genllvm.py
   pypy/dist/pypy/translator/llvm/module/excsupport.py
   pypy/dist/pypy/translator/llvm/pyllvm/test/test_ee.py
   pypy/dist/pypy/translator/llvm/test/runtest.py
   pypy/dist/pypy/translator/llvm/test/test_exc_operation.py
   pypy/dist/pypy/translator/llvm/test/test_exception.py
   pypy/dist/pypy/translator/llvm/test/test_extfunc.py
   pypy/dist/pypy/translator/llvm/wrapable/test/test_llvm.py
Log:
Dusting of genllvm:
    * sharing exceptiontransform with genc
    * using raisingop2direct_call transformation for tests
    * some misc. fixes
    * rewrote some tests because tests that raise exceptions
      currently do not work with the exceptiontransform
    * increased the llvm minimal required version to 1.7
    * wrote a better test for the ringbuffer that hold exceptions


Modified: pypy/dist/pypy/translator/llvm/buildllvm.py
==============================================================================
--- pypy/dist/pypy/translator/llvm/buildllvm.py	(original)
+++ pypy/dist/pypy/translator/llvm/buildllvm.py	Wed May 17 14:36:16 2006
@@ -92,8 +92,8 @@
         source_files = []
 
     if not use_gcc:
-        llc_params = llvm_version() > 1.6 and '-enable-x86-fastcc' or ''
-        if llc_params and exe_name:
+        llc_params = llvm_version() > 1.7 and '-enable-x86-fastcc' or ''
+        if llc_params and exe_name and sys.platform != 'darwin':
             llc_params += ' -relocation-model=static'   #XXX while llvm jumptables not with PIC
         cmds.append("llc %s %s %s.bc -f -o %s.s" % (llc_params, genllvm.db.exceptionpolicy.llc_options(), b, b))
         cmds.append("as %s.s -o %s.o" % (b, b))

Modified: pypy/dist/pypy/translator/llvm/database.py
==============================================================================
--- pypy/dist/pypy/translator/llvm/database.py	(original)
+++ pypy/dist/pypy/translator/llvm/database.py	Wed May 17 14:36:16 2006
@@ -14,7 +14,6 @@
 from pypy.objspace.flow.model import Constant, Variable
 from pypy.rpython.memory.lladdress import NULL
 from pypy.rpython.objectmodel import Symbolic, ComputedIntSymbolic
-from pypy.translator.c.exceptiontransform import ExceptionTransformer
 
 log = log.database 
 
@@ -31,11 +30,6 @@
 
         self.primitives_init()
 
-        if translator is None or translator.rtyper is None:
-            self.exctransformer = None
-        else:
-            self.exctransformer = ExceptionTransformer(translator)
-
     def primitives_init(self):
         primitives = {
             lltype.Char: "sbyte",
@@ -405,9 +399,9 @@
 
         elif isinstance(value, llmemory.CompositeOffset):
             return "cast(%s* getelementptr(%s* null, int 0, uint 1, int %s) to int)" % (
-                self.repr_type(value.second.TYPE),
-                self.repr_type(value.first.TYPE),
-                value.second.repeat)
+                self.repr_type(value.offsets[1].TYPE),
+                self.repr_type(value.offsets[0].TYPE),
+                value.offsets[1].repeat)
         else:
             raise Exception("unsupported offset")
         

Modified: pypy/dist/pypy/translator/llvm/exception.py
==============================================================================
--- pypy/dist/pypy/translator/llvm/exception.py	(original)
+++ pypy/dist/pypy/translator/llvm/exception.py	Wed May 17 14:36:16 2006
@@ -2,13 +2,17 @@
 
 from pypy.translator.llvm.codewriter import DEFAULT_CCONV
 from pypy.translator.llvm.backendopt.exception import create_exception_handling
-from pypy.translator.llvm.module.excsupport import invokeunwind_code, \
-                                                   explicit_code
+from pypy.translator.llvm.module.excsupport import invokeunwind_code, none_code, \
+                                                   explicit_code, exctransform_code
+from pypy.translator.c.exceptiontransform import ExceptionTransformer
+from pypy import conftest
+
 
 def repr_if_variable(db, arg):
     if isinstance(arg, Variable):
         return db.repr_arg(arg)
 
+
 class ExceptionPolicy:
     def __init__(self, db):
         self.db = db
@@ -17,6 +21,22 @@
     def transform(self, translator, graph=None):
         return
 
+    def llvm_declcode(self):
+        return ''
+
+    def llvm_implcode(self, entrynode):
+        return ''
+
+    def llc_options(self):
+    	import sys
+    	if sys.platform == 'linux2' and sys.maxint == 2**63-1:
+            s = '-enable-ia64-dag-isel'
+	else:
+            s = ''
+        #can be used with LLVM debug build...
+        #s += ' -view-legalize-dags -view-isel-dags -view-sched-dags'
+        return s
+    
     def update_phi_data(self, funcnode, entrylinks, block, blocknames):
         """ Exceptions handling code introduces intermediate blocks for
         exception handling cases, hence we modify our input phi data
@@ -57,11 +77,13 @@
         return noresult
 
     def new(db, exceptionpolicy=None):  #factory
-        exceptionpolicy = exceptionpolicy or 'explicit'
+        exceptionpolicy = exceptionpolicy or 'transform' #was: explicit/transform
         if exceptionpolicy == 'invokeunwind':
             exceptionpolicy = InvokeUnwindExceptionPolicy(db)
         elif exceptionpolicy == 'explicit':
             exceptionpolicy = ExplicitExceptionPolicy(db)
+        elif exceptionpolicy == 'transform':
+            exceptionpolicy = TransformExceptionPolicy(db)
         elif exceptionpolicy == 'none':
             exceptionpolicy = NoneExceptionPolicy(db)
         else:
@@ -69,12 +91,45 @@
         return exceptionpolicy
     new = staticmethod(new)
 
+
 class NoneExceptionPolicy(ExceptionPolicy):
     """  XXX untested """
 
     def __init__(self, db):
         self.db = db
 
+    def llvm_implcode(self, entrynode):
+        returntype, entrypointname = entrynode.getdecl().split('%', 1)
+        noresult = self._noresult(returntype)
+        cconv = DEFAULT_CCONV
+        return none_code % locals()
+
+    
+class TransformExceptionPolicy(ExceptionPolicy):
+    def __init__(self, db):
+        self.db = db
+        translator = db.translator
+        if translator is None or translator.rtyper is None:
+            self.exctransformer = None
+        else:
+            self.exctransformer = ExceptionTransformer(translator)
+
+    def llvm_implcode(self, entrynode):
+        returntype, entrypointname = entrynode.getdecl().split('%', 1)
+        noresult = self._noresult(returntype)
+        cconv = DEFAULT_CCONV
+        return exctransform_code % locals()
+
+    def transform(self, translator, graph=None):
+        if self.exctransformer:
+            n_need_exc_matching_blocks, n_gen_exc_checks = \
+                self.exctransformer.create_exception_handling(graph)
+            if n_need_exc_matching_blocks or n_gen_exc_checks:
+                if conftest.option.view:
+                    graph.show()
+                    #self.db.translator.view()
+
+    
 class InvokeUnwindExceptionPolicy(ExceptionPolicy):
     """ uses issubclass() and llvm invoke&unwind
     XXX Untested for a while """
@@ -82,9 +137,6 @@
     def __init__(self):
         pass
 
-    def llvm_declcode(self):
-        return ''
-
     def llvm_implcode(self, entrynode):
         returntype, entrypointname = entrynode.getdecl().split('%', 1)
         noresult = self._noresult(returntype)
@@ -175,15 +227,13 @@
             s = ''
         return '-enable-correct-eh-support' + s
 
+
 class ExplicitExceptionPolicy(ExceptionPolicy):
     """ uses issubclass() and last_exception tests after each call """
     def __init__(self, db):
         self.db = db
         self.invoke_count = 0
 
-    def llvm_declcode(self):
-        return ''
-    
     def llvm_implcode(self, entrynode):
         returntype, entrypointname = entrynode.getdecl().split('%', 1)
         noresult = self._noresult(returntype)
@@ -350,12 +400,3 @@
     def reraise(self, funcnode, codewriter):
         returntype, name, dummy = funcnode.getdecl_parts()
         codewriter.ret(returntype, self._noresult2(returntype))
-
-    def llc_options(self):
-    	import sys
-    	if sys.platform == 'linux2' and sys.maxint == 2**63-1:
-            s = '-enable-ia64-dag-isel'
-	else:
-            s = ''
-        return s
-    

Modified: pypy/dist/pypy/translator/llvm/externs/ringbuffer.py
==============================================================================
--- pypy/dist/pypy/translator/llvm/externs/ringbuffer.py	(original)
+++ pypy/dist/pypy/translator/llvm/externs/ringbuffer.py	Wed May 17 14:36:16 2006
@@ -4,20 +4,25 @@
 # Cant store in class
 size = 8192
 entry_maxsize = 16
+oversize = size + entry_maxsize
 ringbufdata = lltype.malloc(lltype.GcArray(llmemory.Address), 1)
 ringbufindex = lltype.malloc(lltype.GcArray(lltype.Signed), 1)
 
+#note: we could refactor this to not require an index 
+
 def ringbuffer_initialise():
-    ringbufdata[0] = lladdress.raw_malloc(size + entry_maxsize)
+    ringbufdata[0] = lladdress.raw_malloc(oversize)
+    for i in range(oversize):
+        ringbufdata[0].char[i] = '\0' #XXX is there no easier way?
 
 def ringbuffer_malloc(nbytes):
-    assert nbytes <= entry_maxsize
+    #assert nbytes <= entry_maxsize
     addr = ringbufdata[0] + ringbufindex[0]
     ringbufindex[0] = (ringbufindex[0] + nbytes) & (size - 1)
     return addr
 
 # XXX would be nice to support something like this
-# ringbufindex = lltype.malloc(lltype.GcArray(lltype.Char), size + entry_maxsize)
+# ringbufindex = lltype.malloc(lltype.GcArray(lltype.Char), oversize)
 
 # def ringbuffer_initialise():
 #     pass

Modified: pypy/dist/pypy/translator/llvm/externs/test/test_ringbuffer.py
==============================================================================
--- pypy/dist/pypy/translator/llvm/externs/test/test_ringbuffer.py	(original)
+++ pypy/dist/pypy/translator/llvm/externs/test/test_ringbuffer.py	Wed May 17 14:36:16 2006
@@ -23,3 +23,27 @@
     fc = compile(f, [int])
     assert fc(16) == f(16)
     assert fc(10) == f(10)
+    
+def test_ring():
+    def f(init, n_bytes, value):
+        if init:
+            ringbuffer.ringbuffer_initialise()
+            return 42
+        buf           = ringbuffer.ringbuffer_malloc(n_bytes)
+        old_value     = buf.signed[0]
+        buf.signed[0] = value
+        return old_value
+
+    fc = compile(f, [int, int, int])
+    res1 = fc(True, 0, 0)
+    res2 = f(True, 0, 0)
+    assert res1 == 42
+    assert res1 == res2
+    for i in range(ringbuffer.size*3):
+        res1 = fc(False, ringbuffer.entry_maxsize, i)
+        res2 = f(False, ringbuffer.entry_maxsize, i)
+        assert res1 == res2
+        n = ringbuffer.size / ringbuffer.entry_maxsize
+        if i >= n:
+            assert res1 == i - n
+            #print res1, i, n

Modified: pypy/dist/pypy/translator/llvm/funcnode.py
==============================================================================
--- pypy/dist/pypy/translator/llvm/funcnode.py	(original)
+++ pypy/dist/pypy/translator/llvm/funcnode.py	Wed May 17 14:36:16 2006
@@ -31,6 +31,7 @@
 class BranchException(Exception):
     pass
 
+
 class FuncNode(ConstantLLVMNode):
     __slots__ = "db value ref graph block_to_name".split()
 
@@ -44,19 +45,6 @@
         #from pypy.translator.llvm.backendopt.mergemallocs import merge_mallocs
         #merge_mallocs(self.db.translator, self.graph, self.ref)
 
-        # apply the stackless transformation
-        #if db.stacklesstransformer and do_stackless:
-        #    db.stacklesstransformer.transform_graph(graph)
-
-        # apply the exception transformation
-        #if self.db.exctransformer:
-        #    self.db.exctransformer.create_exception_handling(self.graph)
-
-        # apply the gc transformation
-        #self.db.gctransformer.transform_graph(self.graph)
-
-        #self.graph.show()
-
     def __str__(self):
         return "" %(self.ref,)
     
@@ -77,13 +65,14 @@
                         self.db.prepare_constant(type_, link.llexitcase)
                                             
         assert self.graph, "cannot traverse"
+        self.db.exceptionpolicy.transform(self.db.translator, self.graph)
         traverse(visit, self.graph)
 
     # ______________________________________________________________________
     # main entry points from genllvm 
 
     def post_setup_transform(self):
-        self.db.exceptionpolicy.transform(self.db.translator, self.graph)
+        #self.db.exceptionpolicy.transform(self.db.translator, self.graph)
         remove_double_links(self.db.translator, self.graph)
     
     def writedecl(self, codewriter): 

Modified: pypy/dist/pypy/translator/llvm/genllvm.py
==============================================================================
--- pypy/dist/pypy/translator/llvm/genllvm.py	(original)
+++ pypy/dist/pypy/translator/llvm/genllvm.py	Wed May 17 14:36:16 2006
@@ -314,9 +314,10 @@
     t.buildannotator().build_types(function, annotation)
     t.buildrtyper().specialize()
     if optimize:
-        backend_optimizations(t)
+        backend_optimizations(t, raisingop2direct_call_all=True)
     else:
         backend_optimizations(t,
+                              raisingop2direct_call_all=True,
                               inline_threshold=0,
                               mallocs=False,
                               merge_if_blocks_to_switch=False,

Modified: pypy/dist/pypy/translator/llvm/module/excsupport.py
==============================================================================
--- pypy/dist/pypy/translator/llvm/module/excsupport.py	(original)
+++ pypy/dist/pypy/translator/llvm/module/excsupport.py	Wed May 17 14:36:16 2006
@@ -1,5 +1,6 @@
 
 invokeunwind_code = '''
+;XXX this should probably store the last_exception_type
 ccc %(returntype)s%%__entrypoint__%(entrypointname)s {
     %%result = invoke %(cconv)s %(returntype)s%%%(entrypointname)s to label %%no_exception except label %%exception
 
@@ -47,3 +48,45 @@
     ret void
 }
 '''
+
+exctransform_code = '''
+ccc %(returntype)s%%__entrypoint__%(entrypointname)s {
+    store %%RPYTHON_EXCEPTION_VTABLE* null, %%RPYTHON_EXCEPTION_VTABLE** %%last_exception_type
+    %%result = call %(cconv)s %(returntype)s%%%(entrypointname)s
+    %%tmp    = load %%RPYTHON_EXCEPTION_VTABLE** %%last_exception_type
+    %%exc    = seteq %%RPYTHON_EXCEPTION_VTABLE* %%tmp, null
+    br bool %%exc, label %%no_exception, label %%exception
+
+no_exception:
+    ret %(returntype)s %%result
+
+exception:
+    ret %(noresult)s
+}
+
+;XXX this should use the transformation data that has the same purpose
+ccc int %%__entrypoint__raised_LLVMException() {
+    %%tmp    = load %%RPYTHON_EXCEPTION_VTABLE** %%last_exception_type
+    %%result = cast %%RPYTHON_EXCEPTION_VTABLE* %%tmp to int
+    ret int %%result
+}
+
+internal fastcc void %%unwind() {
+    ret void
+}
+'''
+
+none_code = '''
+ccc %(returntype)s%%__entrypoint__%(entrypointname)s {
+    %%result = call %(cconv)s %(returntype)s%%%(entrypointname)s
+    ret %(returntype)s %%result
+}
+
+ccc int %%__entrypoint__raised_LLVMException() {
+    ret int 0
+}
+
+internal fastcc void %%unwind() {
+    ret void
+}
+'''

Modified: pypy/dist/pypy/translator/llvm/pyllvm/test/test_ee.py
==============================================================================
--- pypy/dist/pypy/translator/llvm/pyllvm/test/test_ee.py	(original)
+++ pypy/dist/pypy/translator/llvm/pyllvm/test/test_ee.py	Wed May 17 14:36:16 2006
@@ -3,7 +3,11 @@
 if not llvm_is_on_path():
     py.test.skip("llvm not found")
 
-from pypy.translator.llvm.pyllvm import pyllvm
+try:
+    from pypy.translator.llvm.pyllvm import pyllvm
+except:
+    py.test.skip("Unable to import pyllvm")
+
 from pypy.translator.llvm.pyllvm.test import ll_snippet
 
 

Modified: pypy/dist/pypy/translator/llvm/test/runtest.py
==============================================================================
--- pypy/dist/pypy/translator/llvm/test/runtest.py	(original)
+++ pypy/dist/pypy/translator/llvm/test/runtest.py	Wed May 17 14:36:16 2006
@@ -2,7 +2,7 @@
 from pypy.translator.llvm.genllvm import genllvm_compile
 from pypy.translator.llvm.buildllvm import llvm_is_on_path, llvm_version
 optimize_tests = False
-MINIMUM_LLVM_VERSION = 1.6
+MINIMUM_LLVM_VERSION = 1.7
 
 def llvm_test():
     if not llvm_is_on_path():

Modified: pypy/dist/pypy/translator/llvm/test/test_exc_operation.py
==============================================================================
--- pypy/dist/pypy/translator/llvm/test/test_exc_operation.py	(original)
+++ pypy/dist/pypy/translator/llvm/test/test_exc_operation.py	Wed May 17 14:36:16 2006
@@ -96,6 +96,9 @@
     assert fn(0) == 1234
 
 def test_int_mod_ovf_zer():
+    #without raisingop2direct_call the operation is not found
+    #with    raisingop2direct_call the wrong result is returned
+    py.test.skip("operation int_mod_ovf_zer not found")
     def fn(i):
         try:
             return snippet.mod_func(i)

Modified: pypy/dist/pypy/translator/llvm/test/test_exception.py
==============================================================================
--- pypy/dist/pypy/translator/llvm/test/test_exception.py	(original)
+++ pypy/dist/pypy/translator/llvm/test/test_exception.py	Wed May 17 14:36:16 2006
@@ -95,30 +95,46 @@
     assert f(10) == fn(10)
 
 def test_reraise1():
-    def fn(n):
+    def fnpart2(n):
         lst = range(10)
         try:
             getitem(lst,n)
         except:
             raise
         return 4
+    def fn(n):
+        try:
+            return fnpart2(n)
+        except:
+            return 42
     f = compile_function(fn, [int])
-    py.test.raises(Exception, "f(-1)")
+    assert f(-1) == fn(-1)
+    assert f(-1) == 42
     assert f( 0) == fn( 0)
-    py.test.raises(Exception, "f(10)")
+    assert f( 0) != 42
+    assert f(10) == fn(10)
+    assert f(10) == 42
 
 def test_reraise2():
-    def fn(n):
+    def fnpart2(n):
         lst = range(10)
         try:
             getitem(lst,n)
         except Exception, e:
             raise e
         return 4
+    def fn(n):
+        try:
+            return fnpart2(n)
+        except:
+            return 42
     f = compile_function(fn, [int])
-    py.test.raises(Exception, "f(-1)")
+    assert f(-1) == fn(-1)
+    assert f(-1) == 42
     assert f( 0) == fn( 0)
-    py.test.raises(Exception, "f(10)")
+    assert f( 0) != 42
+    assert f(10) == fn(10)
+    assert f(10) == 42
 
 def test_simple_exception():
     def fn(n):
@@ -251,26 +267,30 @@
         pass
 
     def raise_exception(n):
-        if n == 1: raise A
-        elif n == 0: raise B
+        if n == 1:
+            raise A
+        elif n == 0:
+            raise B
+        else:
+            pass    #i.e. don't raise
         
-    def fn(n):
-        ok = False
+    def fnpart2(n):
         try:
             raise_exception(n)
         except B, exc:
-            ok = True
-        return ok
-    
+            return 10
+        return 20
+
+    def fn(n):
+        try:
+            return fnpart2(n)
+        except:
+            return 765
+
     f = compile_function(fn, [int])
-    res = False
-    assert fn(0)
-    try:
-        f(1)
-    except:
-        res = True
-    assert res
-    assert not f(2)
+    assert f(0) == fn(0)
+    assert f(1) == fn(1)
+    assert f(2) == fn(2)
 
 def no_magic():
     import __builtin__

Modified: pypy/dist/pypy/translator/llvm/test/test_extfunc.py
==============================================================================
--- pypy/dist/pypy/translator/llvm/test/test_extfunc.py	(original)
+++ pypy/dist/pypy/translator/llvm/test/test_extfunc.py	Wed May 17 14:36:16 2006
@@ -23,6 +23,8 @@
     assert abs(f()-fn()) < 10.0
 
 def test_external_function_ll_time_clock():
+    if sys.platform == 'darwin':
+        py.test.skip("time.clock behaving strangly on Darwin")
     import time
     def fn():
         return time.clock()
@@ -233,6 +235,7 @@
     assert f() == False
 
 def test_os_isatty():
+    py.test.skip("os.isatty seems to be hit/miss (since using isolate_module?)")
     def call_isatty(fd):
         return os.isatty(fd)
     f = compile_function(call_isatty, [int])
@@ -340,6 +343,7 @@
         raise ValueError, 'probing for all env vars returned %r' % (output,)
 
 def test_putenv():
+    py.test.skip("putenv seems to be hit/miss (since using isolate_module?)")
     s = 'abcdefgh=12345678'
     def put():
         ros.putenv(s)
@@ -351,6 +355,7 @@
 posix = __import__(os.name)
 if hasattr(posix, "unsetenv"):
     def test_unsetenv():
+        py.test.skip("unsetenv seems to be hit/miss (since using isolate_module?)")
         def unsetenv():
             os.unsetenv("ABCDEF")
             return 0
@@ -391,6 +396,7 @@
     assert result == compared_with
 
 def test_lock():
+    py.test.skip("XXX does not work with exception transform (why not?)")
     import thread
     import pypy.module.thread.rpython.exttable   # for declare()/declaretype()
     def fn():

Modified: pypy/dist/pypy/translator/llvm/wrapable/test/test_llvm.py
==============================================================================
--- pypy/dist/pypy/translator/llvm/wrapable/test/test_llvm.py	(original)
+++ pypy/dist/pypy/translator/llvm/wrapable/test/test_llvm.py	Wed May 17 14:36:16 2006
@@ -1,6 +1,8 @@
 import py
-from pypy.translator.llvm.wrapable.llvm import *
-
+try:
+    from pypy.translator.llvm.wrapable.llvm import *
+except:
+    py.test.skip("unable to import llvm wrapper")
 
 #XXX The tests below were shamefully never written when writing the rest of the code and
 #    should therefor be filled in by Eric asap.


From arigo at codespeak.net  Wed May 17 14:43:28 2006
From: arigo at codespeak.net (arigo at codespeak.net)
Date: Wed, 17 May 2006 14:43:28 +0200 (CEST)
Subject: [pypy-svn] r27360 - in pypy/dist/pypy: rpython rpython/memory
	rpython/memory/test translator/backendopt
Message-ID: <20060517124328.81E6C10034@code0.codespeak.net>

Author: arigo
Date: Wed May 17 14:43:26 2006
New Revision: 27360

Modified:
   pypy/dist/pypy/rpython/annlowlevel.py
   pypy/dist/pypy/rpython/memory/gc.py
   pypy/dist/pypy/rpython/memory/gctransform.py
   pypy/dist/pypy/rpython/memory/gcwrapper.py
   pypy/dist/pypy/rpython/memory/support.py
   pypy/dist/pypy/rpython/memory/test/test_support.py
   pypy/dist/pypy/translator/backendopt/all.py
   pypy/dist/pypy/translator/backendopt/inline.py
Log:
(pedronis, arigo)

Start optimizing the GCs in general.  Next thing is to rewrite the
MarkSweepGC to avoid these AddressLinkedLists.


Modified: pypy/dist/pypy/rpython/annlowlevel.py
==============================================================================
--- pypy/dist/pypy/rpython/annlowlevel.py	(original)
+++ pypy/dist/pypy/rpython/annlowlevel.py	Wed May 17 14:43:26 2006
@@ -120,6 +120,7 @@
         self.delayedreprs = []
         self.delayedconsts = []
         self.delayedfuncs = []
+        self.original_graph_count = len(rtyper.annotator.translator.graphs)
 
     def getgraph(self, ll_function, args_s, s_result):
         # get the graph of the mix-level helper ll_function and prepare it for
@@ -212,3 +213,10 @@
         del self.pending[:]
         del self.delayedreprs[:]
         del self.delayedconsts[:]
+
+    def backend_optimize(self, **flags):
+        # only optimize the newly created graphs
+        from pypy.translator.backendopt.all import backend_optimizations
+        translator = self.rtyper.annotator.translator
+        newgraphs = translator.graphs[self.original_graph_count:]
+        backend_optimizations(translator, newgraphs, **flags)

Modified: pypy/dist/pypy/rpython/memory/gc.py
==============================================================================
--- pypy/dist/pypy/rpython/memory/gc.py	(original)
+++ pypy/dist/pypy/rpython/memory/gc.py	Wed May 17 14:43:26 2006
@@ -191,11 +191,9 @@
         # from this point onwards, no more mallocs should be possible
         old_malloced = self.bytes_malloced
         self.bytes_malloced = 0
-        while 1:  #mark
+        while objects.non_empty():  #mark
             curr = objects.pop()
 ##             print "object: ", curr
-            if curr == NULL:
-                break
             gc_info = curr - size_gc_header
             hdr = llmemory.cast_adr_to_ptr(gc_info, self.HDRPTR)
             if hdr.typeid & 1:
@@ -227,10 +225,9 @@
         newmo = self.AddressLinkedList()
         curr_heap_size = 0
         freed_size = 0
-        while 1:  #sweep
-            curr = self.malloced_objects.pop()
-            if curr == NULL:
-                break
+        malloced_objects = self.malloced_objects
+        while malloced_objects.non_empty():  #sweep
+            curr = malloced_objects.pop()
             hdr = llmemory.cast_adr_to_ptr(curr, self.HDRPTR)
             typeid = hdr.typeid >> 1
             size = self.fixed_size(typeid)
@@ -245,7 +242,7 @@
             else:
                 freed_size += estimate
                 raw_free(curr)
-        self.malloced_objects.delete()
+        malloced_objects.delete()
         self.malloced_objects = newmo
         if curr_heap_size > self.bytes_malloced_threshold:
             self.bytes_malloced_threshold = curr_heap_size
@@ -467,27 +464,21 @@
         roots = roots_copy
         dealloc_list = self.AddressLinkedList()
         self.length_zero_ref_counts = 0
-        while 1:
+        while self.zero_ref_counts.non_empty():
             candidate = self.zero_ref_counts.pop()
-            if candidate == NULL:
-                break
             refcount = self.refcount(candidate)
             typeid = (candidate - self.size_gc_header()).signed[1]
             if (refcount == 0 and typeid >= 0):
                 (candidate - self.size_gc_header()).signed[1] = -typeid - 1
                 dealloc_list.append(candidate)
-        while 1:
+        while dealloc_list.non_empty():
             deallocate = dealloc_list.pop()
-            if deallocate == NULL:
-                break
             typeid = (deallocate - self.size_gc_header()).signed[1]
             (deallocate - self.size_gc_header()).signed[1] = -typeid - 1
             self.deallocate(deallocate)
         dealloc_list.delete()
-        while 1:
+        while roots.non_empty():
             root = roots.pop()
-            if root == NULL:
-                break
             self.decref(root.address[0])
         self.collecting = False
 

Modified: pypy/dist/pypy/rpython/memory/gctransform.py
==============================================================================
--- pypy/dist/pypy/rpython/memory/gctransform.py	(original)
+++ pypy/dist/pypy/rpython/memory/gctransform.py	Wed May 17 14:43:26 2006
@@ -909,6 +909,7 @@
                                     [s_gcdata], annmodel.SomeTuple(statics_s))
                                    
         annhelper.finish()   # at this point, annotate all mix-level helpers
+        annhelper.backend_optimize()
 
         self.collect_analyzer = CollectAnalyzer(self.translator)
         self.collect_analyzer.analyze_all()

Modified: pypy/dist/pypy/rpython/memory/gcwrapper.py
==============================================================================
--- pypy/dist/pypy/rpython/memory/gcwrapper.py	(original)
+++ pypy/dist/pypy/rpython/memory/gcwrapper.py	Wed May 17 14:43:26 2006
@@ -175,7 +175,7 @@
 class GcWrapper(object):
     def __init__(self, llinterp, flowgraphs, gc_class):
         self.query_types = QueryTypes()
-        self.AddressLinkedList = get_address_linked_list(3)
+        self.AddressLinkedList = get_address_linked_list(3, hackishpop=True)
         # XXX there might me GCs that have headers that depend on the type
         # therefore we have to change the query functions to annotatable ones
         # later

Modified: pypy/dist/pypy/rpython/memory/support.py
==============================================================================
--- pypy/dist/pypy/rpython/memory/support.py	(original)
+++ pypy/dist/pypy/rpython/memory/support.py	Wed May 17 14:43:26 2006
@@ -6,7 +6,7 @@
 
 DEFAULT_CHUNK_SIZE = 1019
 
-def get_address_linked_list(chunk_size=DEFAULT_CHUNK_SIZE):
+def get_address_linked_list(chunk_size=DEFAULT_CHUNK_SIZE, hackishpop=False):
 
     CHUNK = lltype.ForwardReference()
     CHUNK.become(lltype.Struct('AddressLinkedListChunk',
@@ -43,31 +43,44 @@
             self.chunk.previous = null_chunk
             self.chunk.length = 0
 
+        def enlarge(self):
+            new = unused_chunks.get()
+            new.previous = self.chunk
+            new.length = 0
+            self.chunk = new
+            return new
+        enlarge.dont_inline = True
+
+        def shrink(self):
+            old = self.chunk
+            self.chunk = old.previous
+            unused_chunks.put(old)
+            return self.chunk
+        shrink.dont_inline = True
+
         def append(self, addr):
             if addr == llmemory.NULL:
                 return
-            if self.chunk.length == chunk_size:
-                new = unused_chunks.get()
-                new.previous = self.chunk
-                new.length = 0
-                self.chunk = new
-            used_chunks = self.chunk.length
-            self.chunk.length += 1
-            self.chunk.items[used_chunks] = addr
-            
+            chunk = self.chunk
+            if chunk.length == chunk_size:
+                chunk = self.enlarge()
+            used_chunks = chunk.length
+            chunk.length = used_chunks + 1
+            chunk.items[used_chunks] = addr
+
+        def non_empty(self):
+            chunk = self.chunk
+            return chunk.length != 0 or bool(chunk.previous)
+
         def pop(self):
-            used_chunks = self.chunk.length
-            if used_chunks == 0:
-                old = self.chunk
-                previous = old.previous
-                if not previous:
-                    return llmemory.NULL
-                self.chunk = previous
-                unused_chunks.put(old)
-                used_chunks = self.chunk.length
-            result = self.chunk.items[used_chunks - 1]
-            #self.chunk.items[used_chunks - 1] = llmemory.NULL
-            self.chunk.length = used_chunks - 1
+            if hackishpop and not self.non_empty():
+                return llmemory.NULL
+            chunk = self.chunk
+            if chunk.length == 0:
+                chunk = self.shrink()
+            used_chunks = self.chunk.length - 1
+            result = chunk.items[used_chunks]
+            chunk.length = used_chunks
             return result
 
         def delete(self):

Modified: pypy/dist/pypy/rpython/memory/test/test_support.py
==============================================================================
--- pypy/dist/pypy/rpython/memory/test/test_support.py	(original)
+++ pypy/dist/pypy/rpython/memory/test/test_support.py	Wed May 17 14:43:26 2006
@@ -13,14 +13,16 @@
         ll.append(addr)
         ll.append(addr + 1)
         ll.append(addr + 2)
+        assert ll.non_empty()
         a = ll.pop()
         assert a - addr == 2
+        assert ll.non_empty()
         a = ll.pop()
         assert a - addr == 1
+        assert ll.non_empty()
         a = ll.pop()
         assert a == addr
-        assert ll.pop() == NULL
-        assert ll.pop() == NULL
+        assert not ll.non_empty()
         ll.append(addr)
         ll.delete()
         ll = AddressLinkedList()
@@ -63,10 +65,10 @@
         res = (a - INT_SIZE*2 == addr)
         a = ll.pop()
         res = res and (a - INT_SIZE*1 == addr)
+        res = res and ll.non_empty()
         a = ll.pop()
         res = res and a == addr
-        res = res and (ll.pop() == NULL)
-        res = res and (ll.pop() == NULL)
+        res = res and not ll.non_empty()
         ll.append(addr)
         for i in range(300):
             ll.append(addr + INT_SIZE*i)

Modified: pypy/dist/pypy/translator/backendopt/all.py
==============================================================================
--- pypy/dist/pypy/translator/backendopt/all.py	(original)
+++ pypy/dist/pypy/translator/backendopt/all.py	Wed May 17 14:43:26 2006
@@ -1,6 +1,6 @@
 from pypy.translator.backendopt.raisingop2direct_call import raisingop2direct_call
 from pypy.translator.backendopt import removenoops
-from pypy.translator.backendopt.inline import auto_inlining
+from pypy.translator.backendopt import inline
 from pypy.translator.backendopt.malloc import remove_simple_mallocs
 from pypy.translator.backendopt.propagate import propagate_all
 from pypy.translator.backendopt.stat import print_statistics
@@ -9,10 +9,12 @@
 from pypy.translator.backendopt.escape import malloc_to_stack
 from pypy.translator.backendopt.mallocprediction import clever_inlining_and_malloc_removal
 from pypy.translator.backendopt.support import log
+from pypy.objspace.flow.model import checkgraph
 
 PRINT_STATISTICS = False
 
-def backend_optimizations(translator, raisingop2direct_call_all=False,
+def backend_optimizations(translator, graphs=None,
+                                      raisingop2direct_call_all=False,
                                       inline_threshold=1,
                                       mallocs=True,
                                       merge_if_blocks_to_switch=True,
@@ -20,15 +22,19 @@
                                       heap2stack=False,
                                       clever_malloc_removal=False):
 
+    if graphs is None:
+        graphs = translator.graphs
+
     if PRINT_STATISTICS:
         print "before optimizations:"
         print_statistics(translator.graphs[0], translator, "per-graph.txt")
 
     if raisingop2direct_call_all:
+        assert graphs is translator.graphs  # XXX for now
         raisingop2direct_call(translator)
 
     # remove obvious no-ops
-    for graph in translator.graphs:
+    for graph in graphs:
         removenoops.remove_same_as(graph)
         simplify.eliminate_empty_blocks(graph)
         simplify.transform_dead_op_vars(graph, translator)
@@ -40,13 +46,16 @@
 
     # ...
     if propagate:
+        assert graphs is translator.graphs  # XXX for now
         propagate_all(translator)
 
     if not clever_malloc_removal:
         # inline functions in each other
         if inline_threshold:
-            auto_inlining(translator, inline_threshold)
-            for graph in translator.graphs:
+            callgraph = inline.inlinable_static_callers(graphs)
+            inline.auto_inlining(translator, inline_threshold,
+                                 callgraph=callgraph)
+            for graph in graphs:
                 removenoops.remove_superfluous_keep_alive(graph)
                 removenoops.remove_duplicate_casts(graph, translator)
 
@@ -57,7 +66,7 @@
         # vaporize mallocs
         if mallocs:
             tot = 0
-            for graph in translator.graphs:
+            for graph in graphs:
                 count = remove_simple_mallocs(graph)
                 if count:
                     # remove typical leftovers from malloc removal
@@ -71,6 +80,7 @@
             print "after malloc removal:"
             print_statistics(translator.graphs[0], translator)
     else:
+        assert graphs is translator.graphs  # XXX for now
         clever_inlining_and_malloc_removal(translator)
 
         if PRINT_STATISTICS:
@@ -78,17 +88,20 @@
             print_statistics(translator.graphs[0], translator)
 
     if propagate:
+        assert graphs is translator.graphs  # XXX for now
         propagate_all(translator)
 
     if heap2stack:
+        assert graphs is translator.graphs  # XXX for now
         malloc_to_stack(translator)
 
     if merge_if_blocks_to_switch:
-        for graph in translator.graphs:
+        for graph in graphs:
             merge_if_blocks(graph)
 
     if PRINT_STATISTICS:
         print "after if-to-switch:"
         print_statistics(translator.graphs[0], translator)
 
-    translator.checkgraphs()
+    for graph in graphs:
+        checkgraph(graph)

Modified: pypy/dist/pypy/translator/backendopt/inline.py
==============================================================================
--- pypy/dist/pypy/translator/backendopt/inline.py	(original)
+++ pypy/dist/pypy/translator/backendopt/inline.py	Wed May 17 14:43:26 2006
@@ -496,11 +496,11 @@
             static_instruction_count(graph))
 
 
-def inlinable_static_callers(translator):
+def inlinable_static_callers(graphs):
     result = []
-    def build_call_graph(node):
-        if isinstance(node, Block):
-            for op in node.operations:
+    for parentgraph in graphs:
+        for block in parentgraph.iterblocks():
+            for op in block.operations:
                 if op.opname == "direct_call":
                     funcobj = op.args[0].value._obj
                     graph = getattr(funcobj, 'graph', None)
@@ -512,8 +512,6 @@
                                    'dont_inline', False):
                             continue
                         result.append((parentgraph, graph))
-    for parentgraph in translator.graphs:
-        traverse(build_call_graph, parentgraph)
     return result
 
 
@@ -524,7 +522,7 @@
     callers = {}     # {graph: {graphs-that-call-it}}
     callees = {}     # {graph: {graphs-that-it-calls}}
     if callgraph is None:
-        callgraph = inlinable_static_callers(translator)
+        callgraph = inlinable_static_callers(translator.graphs)
     for graph1, graph2 in callgraph:
         callers.setdefault(graph2, {})[graph1] = True
         callees.setdefault(graph1, {})[graph2] = True


From antocuni at codespeak.net  Wed May 17 14:59:07 2006
From: antocuni at codespeak.net (antocuni at codespeak.net)
Date: Wed, 17 May 2006 14:59:07 +0200 (CEST)
Subject: [pypy-svn] r27361 - pypy/dist/pypy/rpython/test
Message-ID: <20060517125907.5289A1006E@code0.codespeak.net>

Author: antocuni
Date: Wed May 17 14:58:57 2006
New Revision: 27361

Added:
   pypy/dist/pypy/rpython/test/tool.py   (contents, props changed)
Modified:
   pypy/dist/pypy/rpython/test/test_rlist.py
   pypy/dist/pypy/rpython/test/test_rrange.py
   pypy/dist/pypy/rpython/test/test_rstr.py
   pypy/dist/pypy/rpython/test/test_rtuple.py
Log:
Added the module tool.py that contains some utility for writing tests
to be runned against both typesystem. Refactored tests for rrange,
rstr, rlist and rtuple for taking advantage of the new module.



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	Wed May 17 14:58:57 2006
@@ -12,6 +12,7 @@
 from pypy.rpython.test.test_llinterp import interpret_raises
 from pypy.translator.translator import TranslationContext
 from pypy.objspace.flow.model import Constant, Variable
+from pypy.rpython.test.tool import BaseRtypingTest, LLRtypeMixin, OORtypeMixin
 
 # undo the specialization parameter
 for n1 in 'get set del'.split():
@@ -254,17 +255,7 @@
 
 
 
-class BaseTestListRtyping:
-
-    def interpret(self, fn, args):
-        return interpret(fn, args, type_system=self.ts)
-
-    def interpret_raises(self, exc, fn, args):
-        return interpret_raises(exc, fn, args, type_system=self.ts)
-
-    def _skip_oo(self, reason):
-        if self.ts == 'ootype':
-            py.test.skip("ootypesystem doesn't support %s, yet" % reason)
+class BaseTestRlist(BaseRtypingTest):
 
     def test_simple(self):
         def dummyfn():
@@ -1059,7 +1050,7 @@
 
         t = TranslationContext()
         s = t.buildannotator().build_types(f, [])
-        rtyper = t.buildrtyper(type_system=self.ts)
+        rtyper = t.buildrtyper(type_system=self.type_system)
         rtyper.specialize()
 
         s_A_list = s.items[0]
@@ -1087,7 +1078,7 @@
 
         t = TranslationContext()
         s = t.buildannotator().build_types(f, [])
-        rtyper = t.buildrtyper(type_system=self.ts)
+        rtyper = t.buildrtyper(type_system=self.type_system)
         rtyper.specialize()
 
         s_A_list = s.items[0]
@@ -1128,20 +1119,9 @@
         assert res == 77
 
 
-class TestLltypeRtyping(BaseTestListRtyping):
-
-    ts = "lltype"
+class TestLLtype(BaseTestRlist, LLRtypeMixin):
     rlist = ll_rlist
 
-    def ll_to_list(self, l):
-        return map(None, l.ll_items())[:l.ll_length()]
-
-    def ll_to_string(self, s):
-        return ''.join(s.chars)
-
-    def class_name(self, value):
-        return "".join(value.super.typeptr.name)[:-1]
-
     def test_memoryerror(self):
         def fn(i):
             lst = [0] * i
@@ -1154,16 +1134,5 @@
         self.interpret_raises(MemoryError, fn, [sys.maxint])
     
 
-class TestOotypeRtyping(BaseTestListRtyping):
-
-    ts = "ootype"
+class TestOOtype(BaseTestRlist, OORtypeMixin):
     rlist = oo_rlist
-
-    def ll_to_list(self, l):
-        return l._list[:]
-
-    def ll_to_string(self, s):
-        return s._str
-
-    def class_name(self, value):
-        return ootype.dynamicType(value)._name.split(".")[-1] 

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 May 17 14:58:57 2006
@@ -1,9 +1,9 @@
 from pypy.rpython.rrange import *
-from pypy.rpython.test.test_llinterp import interpret
+from pypy.rpython.test.tool import BaseRtypingTest, LLRtypeMixin, OORtypeMixin
 from pypy.rpython.rarithmetic import intmask
 
 
-class AbstractTestRange:
+class BaseTestRrange(BaseRtypingTest):
 
     def test_rlist_range(self):
         def test1(start, stop, step, varstep):
@@ -34,7 +34,7 @@
             for i in range(N):
                 total += i
             return total
-        res = interpret(dummyfn, [10], type_system=self.ts)
+        res = self.interpret(dummyfn, [10])
         assert res == 45
 
     def test_range_is_lazy(self):
@@ -45,16 +45,16 @@
                     break
                 total += i
             return total
-        res = interpret(dummyfn, [10, 2147418112], type_system=self.ts)
+        res = self.interpret(dummyfn, [10, 2147418112])
         assert res == 45
 
     def test_range_item(self):
         def dummyfn(start, stop, i):
             r = range(start, stop)
             return r[i]
-        res = interpret(dummyfn, [10, 17, 4], type_system=self.ts)
+        res = self.interpret(dummyfn, [10, 17, 4])
         assert res == 14
-        res = interpret(dummyfn, [10, 17, -2], type_system=self.ts)
+        res = self.interpret(dummyfn, [10, 17, -2])
         assert res == 15
 
     def test_xrange(self):
@@ -63,7 +63,7 @@
             for i in xrange(N):
                 total += i
             return total
-        res = interpret(dummyfn, [10], type_system=self.ts)
+        res = self.interpret(dummyfn, [10])
         assert res == 45
 
     def test_range_len(self):
@@ -71,7 +71,7 @@
             r = range(start, stop)
             return len(r)
         start, stop = 10, 17
-        res = interpret(dummyfn, [start, stop], type_system=self.ts)
+        res = self.interpret(dummyfn, [start, stop])
         assert res == dummyfn(start, stop)
 
     def test_range2list(self):
@@ -80,13 +80,12 @@
             r.reverse()
             return r[0]
         start, stop = 10, 17
-        res = interpret(dummyfn, [start, stop], type_system=self.ts)
+        res = self.interpret(dummyfn, [start, stop])
         assert res == dummyfn(start, stop)
 
     def check_failed(self, func, *args):
         try:
-            kwargs = {"type_system": self.ts}
-            interpret(func, *args, **kwargs)
+            self.interpret(func, *args, **kwargs)
         except:
             return True
         else:
@@ -102,7 +101,7 @@
             r = range(10, 17, step)
             return r[-1]
         step = 3
-        res = interpret(failingfn_var, [step], type_system=self.ts)
+        res = self.interpret(failingfn_var, [step])
         assert res == failingfn_var(step)
         step = 0
         assert self.check_failed(failingfn_var, [step])
@@ -121,17 +120,13 @@
                 res = res * 51 + i
             return res
         for args in [2, 7, 0], [7, 2, 0], [10, 50, 7], [50, -10, -3]:
-            res = interpret(fn, args, type_system=self.ts)
+            res = self.interpret(fn, args)
             assert res == intmask(fn(*args))
 
 
-class TestRangeLltype(AbstractTestRange):
-
-    ts = "lltype"
+class TestLLtype(BaseTestRrange, LLRtypeMixin):
     from pypy.rpython.lltypesystem import rrange 
 
 
-class TestRangeOotype(AbstractTestRange):
-
-    ts = "ootype"
+class TestOOtype(BaseTestRrange, OORtypeMixin):
     from pypy.rpython.ootypesystem import rrange 

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	Wed May 17 14:58:57 2006
@@ -3,43 +3,16 @@
 from pypy.rpython.rstr import AbstractLLHelpers
 from pypy.rpython.lltypesystem.rstr import LLHelpers, STR
 from pypy.rpython.rtyper import RPythonTyper, TyperError
-from pypy.rpython.test.test_llinterp import interpret, interpret_raises
+from pypy.rpython.test.tool import BaseRtypingTest, LLRtypeMixin, OORtypeMixin
 from pypy.rpython.llinterp import LLException
 
-def llstr(s):
-    p = malloc(STR, len(s))
-    for i in range(len(s)):
-        p.chars[i] = s[i]
-    return p
-
-def test_ll_find_rfind():
-    for i in range(50):
-        n1 = random.randint(0, 10)
-        s1 = ''.join([random.choice("ab") for i in range(n1)])
-        n2 = random.randint(0, 5)
-        s2 = ''.join([random.choice("ab") for i in range(n2)])
-        res = LLHelpers.ll_find(llstr(s1), llstr(s2), 0, n1)
-        assert res == s1.find(s2)
-        res = LLHelpers.ll_rfind(llstr(s1), llstr(s2), 0, n1)
-        assert res == s1.rfind(s2)
-
 def test_parse_fmt():
-    assert AbstractLLHelpers.parse_fmt_string('a') == ['a']
-    assert AbstractLLHelpers.parse_fmt_string('%s') == [('s',)]
-    assert AbstractLLHelpers.parse_fmt_string("name '%s' is not defined") == ["name '", ("s",), "' is not defined"]
-
-
-class AbstractTestRstr:
-
-    def interpret(self, fn, args):
-        return interpret(fn, args, type_system=self.ts)
+    parse = AbstractLLHelpers.parse_fmt_string
+    assert parse('a') == ['a']
+    assert parse('%s') == [('s',)]
+    assert parse("name '%s' is not defined") == ["name '", ("s",), "' is not defined"]
 
-    def interpret_raises(self, exc, fn, args):
-        return interpret_raises(exc, fn, args, type_system=self.ts)
-
-    def _skip_oo(self, reason):
-        if self.ts == 'ootype':
-            py.test.skip("ootypesystem doesn't support %s, yet" % reason)
+class BaseTestRstr(BaseRtypingTest):
 
     def test_simple(self):
         def fn(i):
@@ -513,11 +486,11 @@
         def fn():
             s = 'abbccc'
             s = s.replace('a', 'baz')
-        raises (TyperError, interpret, fn, ())
+        raises(TyperError, self.interpret, fn, ())
         def fn():
             s = 'abbccc'
             s = s.replace('abb', 'c')
-        raises (TyperError, interpret, fn, ())
+        raises(TyperError, self.interpret, fn, ())
 
     def test_int(self):
         s1 = [ '42', '01001', 'abc', 'ABC', '4aBc', ' 12ef ', '+42', 'foo', '42foo', '42.1', '']
@@ -580,11 +553,25 @@
     res = interpret(g, [-2])
     assert res._obj.value == 42
 
-class TestLltype(AbstractTestRstr):
-    ts = "lltype"
+class TestLLtype(BaseTestRstr, LLRtypeMixin):
+
+    def llstr(self, s):
+        p = malloc(STR, len(s))
+        for i in range(len(s)):
+            p.chars[i] = s[i]
+        return p
+
+    def test_ll_find_rfind(self):
+        for i in range(50):
+            n1 = random.randint(0, 10)
+            s1 = ''.join([random.choice("ab") for i in range(n1)])
+            n2 = random.randint(0, 5)
+            s2 = ''.join([random.choice("ab") for i in range(n2)])
+            res = LLHelpers.ll_find(self.llstr(s1), self.llstr(s2), 0, n1)
+            assert res == s1.find(s2)
+            res = LLHelpers.ll_rfind(self.llstr(s1), self.llstr(s2), 0, n1)
+            assert res == s1.rfind(s2)
 
-    def ll_to_string(self, s):
-        return ''.join(s.chars)
 
     def test_hash(self):
         def fn(i):
@@ -599,8 +586,5 @@
         assert typeOf(res) == Signed
 
 
-class TestOotype(AbstractTestRstr):
-    ts = "ootype"
-
-    def ll_to_string(self, s):
-        return s._str
+class TestOOtype(BaseTestRstr, OORtypeMixin):
+    pass

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	Wed May 17 14:58:57 2006
@@ -3,7 +3,8 @@
 from pypy.rpython.ootypesystem import ootype
 from pypy.rpython.rint import signed_repr
 from pypy.rpython.rbool import bool_repr
-from pypy.rpython.test.test_llinterp import interpret 
+from pypy.rpython.test.test_llinterp import interpret
+from pypy.rpython.test.tool import BaseRtypingTest, LLRtypeMixin, OORtypeMixin
 import py
 
 def test_rtuple():
@@ -16,10 +17,7 @@
 
 # ____________________________________________________________
 
-class AbstractTestRTuple:
-
-    def interpret(self, f, args):
-        return interpret(f, args, type_system=self.type_system)
+class BaseTestRtuple(BaseRtypingTest):
 
     def test_simple(self):
         def dummyfn(x):
@@ -88,8 +86,6 @@
         assert res is False 
 
     def test_conv(self):
-        if self.type_system == "ootype":
-            py.test.skip("fix me if ootypes supports strings")
         def t0():
             return (3, 2, None)
         def t1():
@@ -102,13 +98,11 @@
 
         res = self.interpret(f, [1])
         assert res.item0 == 7
-        # XXX this assertion will fail once ootypesystem properly supports
-        # strings, we're leaving the fix up to that point
-        assert isinstance(typeOf(res.item2), Ptr) and ''.join(res.item2.chars) == "xy"
+        assert self.ll_to_string(res.item2) == "xy"
+
         res = self.interpret(f, [0])
         assert res.item0 == 3
-        # XXX see above
-        assert isinstance(typeOf(res.item2), Ptr) and not res.item2
+        assert not res.item2
 
     def test_constant_tuples_shared(self):
         def g(n):
@@ -193,10 +187,7 @@
             return list((i, j))
 
         res = self.interpret(f, [2, 3])
-        if self.type_system == "lltype":
-            assert res._obj.items == [2, 3]
-        else:
-            assert res._list == [2, 3]
+        assert self.ll_to_list(res) == [2, 3]
 
     def test_tuple_iterator_length1(self):
         def f(i):
@@ -239,17 +230,9 @@
         res = self.interpret(g, [3])
         assert res == 3
 
-class TestLLTuple(AbstractTestRTuple):
-
-    type_system = "lltype"
-
-    def class_name(self, value):
-        return "".join(value.super.typeptr.name)[:-1]
-
-class TestOOTuple(AbstractTestRTuple):
-
-    type_system = "ootype"
+class TestLLtype(BaseTestRtuple, LLRtypeMixin):
+    pass
 
-    def class_name(self, value):
-        return ootype.dynamicType(value)._name.split(".")[-1] 
+class TestOOtype(BaseTestRtuple, OORtypeMixin):
+    pass
 

Added: pypy/dist/pypy/rpython/test/tool.py
==============================================================================
--- (empty file)
+++ pypy/dist/pypy/rpython/test/tool.py	Wed May 17 14:58:57 2006
@@ -0,0 +1,40 @@
+import py
+from pypy.rpython.ootypesystem import ootype
+from pypy.rpython.test.test_llinterp import interpret, interpret_raises
+
+class BaseRtypingTest(object):
+    def interpret(self, fn, args):
+        return interpret(fn, args, type_system=self.type_system)
+
+    def interpret_raises(self, exc, fn, args):
+        return interpret_raises(exc, fn, args, type_system=self.type_system)
+
+    def _skip_oo(self, reason):
+        if self.type_system == 'ootype':
+            py.test.skip("ootypesystem doesn't support %s, yet" % reason)
+    
+
+class LLRtypeMixin(object):
+    type_system = 'lltype'
+
+    def ll_to_string(self, s):
+        return ''.join(s.chars)
+
+    def ll_to_list(self, l):
+        return map(None, l.ll_items())[:l.ll_length()]
+
+    def class_name(self, value):
+        return "".join(value.super.typeptr.name)[:-1]
+
+
+class OORtypeMixin(object):
+    type_system = 'ootype'
+
+    def ll_to_string(self, s):
+        return s._str
+
+    def ll_to_list(self, l):
+        return l._list[:]
+
+    def class_name(self, value):
+        return ootype.dynamicType(value)._name.split(".")[-1] 


From mwh at codespeak.net  Wed May 17 15:09:30 2006
From: mwh at codespeak.net (mwh at codespeak.net)
Date: Wed, 17 May 2006 15:09:30 +0200 (CEST)
Subject: [pypy-svn] r27363 - in pypy/dist/pypy: rpython/memory translator/c
Message-ID: <20060517130930.7024310060@code0.codespeak.net>

Author: mwh
Date: Wed May 17 15:09:28 2006
New Revision: 27363

Modified:
   pypy/dist/pypy/rpython/memory/gctransform.py
   pypy/dist/pypy/translator/c/funcgen.py
   pypy/dist/pypy/translator/c/gc.py
   pypy/dist/pypy/translator/c/primitive.py
Log:
do weak address hiding (if needed) in the backend rather than in the
gctransformer.


Modified: pypy/dist/pypy/rpython/memory/gctransform.py
==============================================================================
--- pypy/dist/pypy/rpython/memory/gctransform.py	(original)
+++ pypy/dist/pypy/rpython/memory/gctransform.py	Wed May 17 15:09:28 2006
@@ -660,28 +660,6 @@
         """ for boehm it is enough to do nothing"""
         return [SpaceOperation("same_as", [Constant(None, lltype.Void)], op.result)]
 
-    def replace_cast_ptr_to_weakadr(self, op, livevars, block):
-        result = []
-        intvar = varoftype(lltype.Signed)
-        invertvar = varoftype(lltype.Signed)
-        ptrvar = varoftype(op.args[0].concretetype)
-        result.append(SpaceOperation("cast_ptr_to_int", [op.args[0]], intvar))
-        result.append(SpaceOperation("int_invert", [intvar], invertvar))
-        result.append(SpaceOperation("cast_int_to_ptr", [invertvar], ptrvar))
-        result.append(SpaceOperation("cast_ptr_to_weakadr", [ptrvar], op.result))
-        return result
-
-    def replace_cast_weakadr_to_ptr(self, op, livevars, block):
-        result = []
-        intvar = varoftype(lltype.Signed)
-        invertvar = varoftype(lltype.Signed)
-        ptrvar = varoftype(op.args[0].concretetype)
-        result.append(SpaceOperation("cast_weakadr_to_ptr", [op.args[0]], ptrvar))
-        result.append(SpaceOperation("cast_ptr_to_int", [ptrvar], intvar))
-        result.append(SpaceOperation("int_invert", [intvar], invertvar))
-        result.append(SpaceOperation("cast_int_to_ptr", [invertvar], op.result))
-        return result
-
     def get_rtti(self, TYPE):
         if isinstance(TYPE, lltype.GcStruct):
             try:

Modified: pypy/dist/pypy/translator/c/funcgen.py
==============================================================================
--- pypy/dist/pypy/translator/c/funcgen.py	(original)
+++ pypy/dist/pypy/translator/c/funcgen.py	Wed May 17 15:09:28 2006
@@ -594,9 +594,18 @@
     OP_CAST_PTR_TO_ADR = OP_CAST_POINTER
     OP_CAST_ADR_TO_PTR = OP_CAST_POINTER
     OP_CAST_OPAQUE_PTR = OP_CAST_POINTER
-    OP_CAST_PTR_TO_WEAKADR = OP_CAST_POINTER
-    OP_CAST_WEAKADR_TO_PTR = OP_CAST_POINTER
 
+    def OP_CAST_PTR_TO_WEAKADR(self, op):
+        return '\t%s = HIDE_POINTER(%s);' % (self.expr(op.result),
+                                             self.expr(op.args[0]))
+
+    def OP_CAST_WEAKADR_TO_PTR(self, op):
+        TYPE = self.lltypemap(op.result)
+        assert TYPE != PyObjPtr
+        typename = self.db.gettype(TYPE)
+        return '\t%s = (%s)REVEAL_POINTER(%s);' % (self.expr(op.result),
+                                                   cdecl(typename, ''),
+                                                   self.expr(op.args[0]))
 
     def OP_CAST_INT_TO_PTR(self, op):
         TYPE = self.lltypemap(op.result)

Modified: pypy/dist/pypy/translator/c/gc.py
==============================================================================
--- pypy/dist/pypy/translator/c/gc.py	(original)
+++ pypy/dist/pypy/translator/c/gc.py	Wed May 17 15:09:28 2006
@@ -80,6 +80,12 @@
     def common_gcheader_initdata(self, defnode):
         return [REFCOUNT_IMMORTAL()]
 
+    def pre_gc_code(self):
+        return ['#define HIDE_POINTER(p) (p)',
+                '#define REVEAL_POINTER(p) (p)',
+                'typedef void *GC_hidden_pointer;']
+
+
     # for structs
 
     def struct_setup(self, structdefnode, rtti):
@@ -208,9 +214,11 @@
             yield "#define _REENTRANT 1"
             yield "#define GC_LINUX_THREADS 1"
             yield "#define GC_REDIRECT_TO_LOCAL 1"
+            yield "#define GC_I_HIDE_POINTERS 1"
             yield '#include '
             yield '#define USING_BOEHM_GC'
         else:
+            yield "#define GC_I_HIDE_POINTERS 1"
             yield '#include '
             yield '#define USING_BOEHM_GC'
 
@@ -342,6 +350,11 @@
     def pre_pre_gc_code(self):
         yield '#define USING_NO_GC'
 
+    def pre_gc_code(self):
+        return ['#define HIDE_POINTER(p) (p)',
+                '#define REVEAL_POINTER(p) (p)',
+                'typedef void *GC_hidden_pointer;']
+
 
 class FrameworkGcPolicy(BasicGcPolicy):
     transformerclass = gctransform.FrameworkGCTransformer

Modified: pypy/dist/pypy/translator/c/primitive.py
==============================================================================
--- pypy/dist/pypy/translator/c/primitive.py	(original)
+++ pypy/dist/pypy/translator/c/primitive.py	Wed May 17 15:09:28 2006
@@ -155,7 +155,7 @@
     Bool:     '((char) -1)',
     Void:     '/* error */',
     Address:  'NULL',
-    WeakGcAddress:  'NULL',
+    WeakGcAddress:  'HIDE_POINTER(NULL)',
     }
 
 def define_c_primitive(ll_type, c_name):


From cfbolz at codespeak.net  Wed May 17 15:09:57 2006
From: cfbolz at codespeak.net (cfbolz at codespeak.net)
Date: Wed, 17 May 2006 15:09:57 +0200 (CEST)
Subject: [pypy-svn] r27364 - pypy/dist/pypy/module/_weakref
Message-ID: <20060517130957.754F410064@code0.codespeak.net>

Author: cfbolz
Date: Wed May 17 15:09:56 2006
New Revision: 27364

Modified:
   pypy/dist/pypy/module/_weakref/interp__weakref.py
Log:
fix bug in weakrefs (thanks armin). hard to write a test for it :-(. you could
see the problem by looking at the output, but since the test passes it is not
shown by default.


Modified: pypy/dist/pypy/module/_weakref/interp__weakref.py
==============================================================================
--- pypy/dist/pypy/module/_weakref/interp__weakref.py	(original)
+++ pypy/dist/pypy/module/_weakref/interp__weakref.py	Wed May 17 15:09:56 2006
@@ -92,6 +92,7 @@
         
     def invalidate(w_self):
         w_self.address = WEAKNULL
+        w_self.addr_lifeline = WEAKNULL
 
     def activate_callback(w_self):
         if not w_self.space.is_w(w_self.w_callable, w_self.space.w_None):


From arigo at codespeak.net  Wed May 17 15:44:30 2006
From: arigo at codespeak.net (arigo at codespeak.net)
Date: Wed, 17 May 2006 15:44:30 +0200 (CEST)
Subject: [pypy-svn] r27365 - pypy/dist/pypy/rpython/memory
Message-ID: <20060517134430.5568310053@code0.codespeak.net>

Author: arigo
Date: Wed May 17 15:44:27 2006
New Revision: 27365

Modified:
   pypy/dist/pypy/rpython/memory/gctransform.py
Log:
(pedronis, arigo scared)

For the StacklessGcFramework, replace mallocs by calls to the
function, and immediately inline that, as soon as possible,
before the stackless transformer does anything.  See comments.


Modified: pypy/dist/pypy/rpython/memory/gctransform.py
==============================================================================
--- pypy/dist/pypy/rpython/memory/gctransform.py	(original)
+++ pypy/dist/pypy/rpython/memory/gctransform.py	Wed May 17 15:44:27 2006
@@ -9,6 +9,7 @@
 from pypy.translator.unsimplify import remove_empty_startblock
 from pypy.translator.translator import graphof
 from pypy.translator.backendopt.support import var_needsgc, needs_conservative_livevar_calculation
+from pypy.translator.backendopt import inline
 from pypy.translator.backendopt import graphanalyze
 from pypy.translator.backendopt.ssa import DataFlowFamilyBuilder
 from pypy.annotation import model as annmodel
@@ -124,14 +125,14 @@
 
     def inline_helpers(self, graph):
         if self.inline:
-            from pypy.translator.backendopt import inline
             for inline_graph in self.graphs_to_inline:
                 try:
                     # XXX quite inefficient: we go over the function lots of times
                     inline.inline_function(self.translator, inline_graph, graph,
                                            self.lltype_to_classdef)
-                except inline.CannotInline:
-                    pass
+                except inline.CannotInline, e:
+                    print 'CANNOT INLINE:', e
+                    print '\t%s into %s' % (inline_graph, graph)
             checkgraph(graph)
 
     def transform_block(self, block, is_borrowed):
@@ -1227,6 +1228,36 @@
     extra_static_slots = 1     # for the stack_capture()'d frame
     MinimalGCTransformer = StacklessFrameworkMinimalGCTransformer
 
+    def __init__(self, translator):
+        FrameworkGCTransformer.__init__(self, translator)
+        # and now, fun fun fun, we need to inline malloc_fixedsize
+        # manually into all 'malloc' operation users, because inlining
+        # it after it has been stackless transformed is both a Very
+        # Bad Idea and forbidden by the fact that stackless transform
+        # makes it self-recursive!  Argh.
+        self.replace_and_inline_malloc_already_now()
+        # nothing left to inline during code generation
+        self.inline = False
+
+    def replace_and_inline_malloc_already_now(self):
+        for graph in self.translator.graphs:
+            any_malloc = False
+            for block in graph.iterblocks():
+                if block.operations:
+                    newops = []
+                    for op in block.operations:
+                        if op.opname.startswith('malloc'):
+                            any_malloc = True
+                            ops = self.replace_malloc(op, [], block)
+                            if isinstance(ops, tuple):
+                                ops = ops[0]
+                            newops.extend(ops)
+                        else:
+                            newops.append(op)
+                    block.operations = newops
+            if any_malloc:
+                self.inline_helpers(graph)
+
     def build_stack_root_iterator(self):
         from pypy.rpython.rstack import stack_capture
         sizeofaddr = llmemory.sizeof(llmemory.Address)


From arigo at codespeak.net  Wed May 17 16:34:54 2006
From: arigo at codespeak.net (arigo at codespeak.net)
Date: Wed, 17 May 2006 16:34:54 +0200 (CEST)
Subject: [pypy-svn] r27366 - pypy/dist/pypy/rpython/memory
Message-ID: <20060517143454.B06F910063@code0.codespeak.net>

Author: arigo
Date: Wed May 17 16:34:53 2006
New Revision: 27366

Modified:
   pypy/dist/pypy/rpython/memory/gc.py
Log:
Replace the malloced_objects AddressLinkedList with a normal
linked list following the headers of the objects.  Gives a
small speed-up in targetgcbench.


Modified: pypy/dist/pypy/rpython/memory/gc.py
==============================================================================
--- pypy/dist/pypy/rpython/memory/gc.py	(original)
+++ pypy/dist/pypy/rpython/memory/gc.py	Wed May 17 16:34:53 2006
@@ -104,25 +104,24 @@
 class MarkSweepGC(GCBase):
     _alloc_flavor_ = "raw"
 
-    HDR = lltype.Struct('header', ('typeid', lltype.Signed))
+    HDR = lltype.ForwardReference()
     HDRPTR = lltype.Ptr(HDR)
+    # need to maintain a linked list of malloced objects, since we used the
+    # systems allocator and can't walk the heap
+    HDR.become(lltype.Struct('header', ('typeid', lltype.Signed),
+                                       ('next', HDRPTR)))
 
     def __init__(self, AddressLinkedList, start_heap_size=4096, get_roots=None):
         self.heap_usage = 0          # at the end of the latest collection
         self.bytes_malloced = 0      # since the latest collection
         self.bytes_malloced_threshold = start_heap_size
         self.total_collection_time = 0.0
-        #need to maintain a list of malloced objects, since we used the systems
-        #allocator and can't walk the heap
-        self.malloced_objects = None
         self.AddressLinkedList = AddressLinkedList
         #self.set_query_functions(None, None, None, None, None, None, None)
+        self.malloced_objects = lltype.nullptr(self.HDR)
         self.get_roots = get_roots
         self.gcheaderbuilder = GCHeaderBuilder(self.HDR)
 
-    def setup(self):
-        self.malloced_objects = self.AddressLinkedList()
-
     def malloc(self, typeid, length=0):
         size = self.fixed_size(typeid)
         if self.is_varsize(typeid):
@@ -143,7 +142,8 @@
         result = raw_malloc(size_gc_header + size)
         hdr = llmemory.cast_adr_to_ptr(result, self.HDRPTR)
         hdr.typeid = typeid << 1
-        self.malloced_objects.append(result)
+        hdr.next = self.malloced_objects
+        self.malloced_objects = hdr
         self.bytes_malloced += raw_malloc_usage(size + size_gc_header)
         result += size_gc_header
         return llmemory.cast_adr_to_ptr(result, llmemory.GCREF)
@@ -163,7 +163,8 @@
         (result + size_gc_header + offset_to_length).signed[0] = length
         hdr = llmemory.cast_adr_to_ptr(result, self.HDRPTR)
         hdr.typeid = typeid << 1
-        self.malloced_objects.append(result)
+        hdr.next = self.malloced_objects
+        self.malloced_objects = hdr
         self.bytes_malloced += raw_malloc_usage(size + size_gc_header)
         result += size_gc_header
         return llmemory.cast_adr_to_ptr(result, llmemory.GCREF)
@@ -225,24 +226,26 @@
         newmo = self.AddressLinkedList()
         curr_heap_size = 0
         freed_size = 0
-        malloced_objects = self.malloced_objects
-        while malloced_objects.non_empty():  #sweep
-            curr = malloced_objects.pop()
-            hdr = llmemory.cast_adr_to_ptr(curr, self.HDRPTR)
+        hdr = self.malloced_objects
+        newmo = lltype.nullptr(self.HDR)
+        while hdr:  #sweep
             typeid = hdr.typeid >> 1
+            next = hdr.next
+            addr = llmemory.cast_ptr_to_adr(hdr)
             size = self.fixed_size(typeid)
             if self.is_varsize(typeid):
-                length = (curr + size_gc_header + self.varsize_offset_to_length(typeid)).signed[0]
+                length = (addr + size_gc_header + self.varsize_offset_to_length(typeid)).signed[0]
                 size += self.varsize_item_sizes(typeid) * length
             estimate = raw_malloc_usage(size_gc_header + size)
             if hdr.typeid & 1:
                 hdr.typeid = hdr.typeid & (~1)
-                newmo.append(curr)
+                hdr.next = newmo
+                newmo = hdr
                 curr_heap_size += estimate
             else:
                 freed_size += estimate
-                raw_free(curr)
-        malloced_objects.delete()
+                raw_free(addr)
+            hdr = next
         self.malloced_objects = newmo
         if curr_heap_size > self.bytes_malloced_threshold:
             self.bytes_malloced_threshold = curr_heap_size


From mwh at codespeak.net  Wed May 17 16:48:12 2006
From: mwh at codespeak.net (mwh at codespeak.net)
Date: Wed, 17 May 2006 16:48:12 +0200 (CEST)
Subject: [pypy-svn] r27367 - in pypy/dist/pypy/translator/c: . src
Message-ID: <20060517144812.5333F10063@code0.codespeak.net>

Author: mwh
Date: Wed May 17 16:48:10 2006
New Revision: 27367

Modified:
   pypy/dist/pypy/translator/c/gc.py
   pypy/dist/pypy/translator/c/src/address.h
Log:
do the declarations necessary for address hiding in genc in a slightly saner
way.


Modified: pypy/dist/pypy/translator/c/gc.py
==============================================================================
--- pypy/dist/pypy/translator/c/gc.py	(original)
+++ pypy/dist/pypy/translator/c/gc.py	Wed May 17 16:48:10 2006
@@ -44,7 +44,7 @@
         return []
 
     def pre_gc_code(self):
-        return []
+        return ['typedef void *GC_hidden_pointer;']
 
     def gc_startup_code(self):
         return []
@@ -80,12 +80,6 @@
     def common_gcheader_initdata(self, defnode):
         return [REFCOUNT_IMMORTAL()]
 
-    def pre_gc_code(self):
-        return ['#define HIDE_POINTER(p) (p)',
-                '#define REVEAL_POINTER(p) (p)',
-                'typedef void *GC_hidden_pointer;']
-
-
     # for structs
 
     def struct_setup(self, structdefnode, rtti):
@@ -222,6 +216,9 @@
             yield '#include '
             yield '#define USING_BOEHM_GC'
 
+    def pre_gc_code(self):
+        return []
+
     def gc_startup_code(self):
         if sys.platform == 'win32':
             pass # yield 'assert(GC_all_interior_pointers == 0);'
@@ -350,11 +347,6 @@
     def pre_pre_gc_code(self):
         yield '#define USING_NO_GC'
 
-    def pre_gc_code(self):
-        return ['#define HIDE_POINTER(p) (p)',
-                '#define REVEAL_POINTER(p) (p)',
-                'typedef void *GC_hidden_pointer;']
-
 
 class FrameworkGcPolicy(BasicGcPolicy):
     transformerclass = gctransform.FrameworkGCTransformer
@@ -375,9 +367,6 @@
         fnptr = self.db.gctransformer.frameworkgc_setup_ptr.value
         yield '%s();' % (self.db.get(fnptr),)
 
-    def pre_gc_code(self):
-        return []
-
     def OP_GC_RELOAD_POSSIBLY_MOVED(self, funcgen, op):
         args = [funcgen.expr(v) for v in op.args]
         # XXX this more or less assumes mark-and-sweep gc

Modified: pypy/dist/pypy/translator/c/src/address.h
==============================================================================
--- pypy/dist/pypy/translator/c/src/address.h	(original)
+++ pypy/dist/pypy/translator/c/src/address.h	Wed May 17 16:48:10 2006
@@ -16,3 +16,10 @@
 #define OP_ADR_LT(x,y,r)	  r = ((x) <  (y))
 #define OP_ADR_GE(x,y,r)	  r = ((x) >= (y))
 
+#ifndef HIDE_POINTER
+#define HIDE_POINTER(p) (p)
+#ifdef REVEAL_POINTER
+#error HIDE_POINTER but not REVEAL_POINTER?
+#endif
+#define REVEAL_POINTER(p) (p)
+#endif


From mwh at codespeak.net  Wed May 17 17:39:22 2006
From: mwh at codespeak.net (mwh at codespeak.net)
Date: Wed, 17 May 2006 17:39:22 +0200 (CEST)
Subject: [pypy-svn] r27369 - pypy/dist/pypy/translator/c
Message-ID: <20060517153922.2A30A10063@code0.codespeak.net>

Author: mwh
Date: Wed May 17 17:39:20 2006
New Revision: 27369

Modified:
   pypy/dist/pypy/translator/c/funcgen.py
Log:
remove extraneous tabs


Modified: pypy/dist/pypy/translator/c/funcgen.py
==============================================================================
--- pypy/dist/pypy/translator/c/funcgen.py	(original)
+++ pypy/dist/pypy/translator/c/funcgen.py	Wed May 17 17:39:20 2006
@@ -596,14 +596,14 @@
     OP_CAST_OPAQUE_PTR = OP_CAST_POINTER
 
     def OP_CAST_PTR_TO_WEAKADR(self, op):
-        return '\t%s = HIDE_POINTER(%s);' % (self.expr(op.result),
+        return '%s = HIDE_POINTER(%s);' % (self.expr(op.result),
                                              self.expr(op.args[0]))
 
     def OP_CAST_WEAKADR_TO_PTR(self, op):
         TYPE = self.lltypemap(op.result)
         assert TYPE != PyObjPtr
         typename = self.db.gettype(TYPE)
-        return '\t%s = (%s)REVEAL_POINTER(%s);' % (self.expr(op.result),
+        return '%s = (%s)REVEAL_POINTER(%s);' % (self.expr(op.result),
                                                    cdecl(typename, ''),
                                                    self.expr(op.args[0]))
 


From mwh at codespeak.net  Wed May 17 17:59:48 2006
From: mwh at codespeak.net (mwh at codespeak.net)
Date: Wed, 17 May 2006 17:59:48 +0200 (CEST)
Subject: [pypy-svn] r27372 - pypy/dist/pypy/translator/c
Message-ID: <20060517155948.59ED810063@code0.codespeak.net>

Author: mwh
Date: Wed May 17 17:59:47 2006
New Revision: 27372

Modified:
   pypy/dist/pypy/translator/c/primitive.py
Log:
argh!  i only made the least important of the three needed changes to
primitive.py :(


Modified: pypy/dist/pypy/translator/c/primitive.py
==============================================================================
--- pypy/dist/pypy/translator/c/primitive.py	(original)
+++ pypy/dist/pypy/translator/c/primitive.py	Wed May 17 17:59:47 2006
@@ -113,7 +113,7 @@
 def name_weakgcaddress(value, db):
     assert isinstance(value, fakeweakaddress)
     assert value.ref is None # only weak NULL supported
-    return 'NULL'
+    return 'HIDE_POINTER(NULL)'
 
 
 PrimitiveName = {
@@ -141,7 +141,7 @@
     Bool:     'char @',
     Void:     'void @',
     Address:  'void* @',
-    WeakGcAddress:  'void* @',
+    WeakGcAddress:  'GC_hidden_pointer @',
     }
 
 PrimitiveErrorValue = {


From arigo at codespeak.net  Wed May 17 18:06:44 2006
From: arigo at codespeak.net (arigo at codespeak.net)
Date: Wed, 17 May 2006 18:06:44 +0200 (CEST)
Subject: [pypy-svn] r27373 - pypy/dist/pypy/translator/c
Message-ID: <20060517160644.8C8BB10061@code0.codespeak.net>

Author: arigo
Date: Wed May 17 18:06:43 2006
New Revision: 27373

Modified:
   pypy/dist/pypy/translator/c/primitive.py
Log:
(pedronis, arigo)

The nice helper function above was intended to be used.


Modified: pypy/dist/pypy/translator/c/primitive.py
==============================================================================
--- pypy/dist/pypy/translator/c/primitive.py	(original)
+++ pypy/dist/pypy/translator/c/primitive.py	Wed May 17 18:06:43 2006
@@ -185,9 +185,4 @@
                             (rcarith.CULong, 'unsigned long'),
                             (rcarith.CLonglong, 'long long'),
                             (rcarith.CULonglong, 'unsigned long long')]:
-        if ll_type in PrimitiveName:
-            continue
-        PrimitiveName[ll_type] = lambda value, db, c_name=c_name: '((%s) %dULL)' % (c_name, value)
-        PrimitiveType[ll_type] = '%s @'% c_name
-        PrimitiveErrorValue[ll_type] = '((%s) -1)'% c_name
-    
+        define_c_primitive(ll_type, c_name)


From stephan at codespeak.net  Wed May 17 18:22:00 2006
From: stephan at codespeak.net (stephan at codespeak.net)
Date: Wed, 17 May 2006 18:22:00 +0200 (CEST)
Subject: [pypy-svn] r27374 - pypy/dist/pypy/module/stackless/test
Message-ID: <20060517162200.141C610061@code0.codespeak.net>

Author: stephan
Date: Wed May 17 18:21:58 2006
New Revision: 27374

Added:
   pypy/dist/pypy/module/stackless/test/stackless_firsttry.py
      - copied unchanged from r27239, pypy/dist/pypy/module/stackless/test/stackless_.py
Modified:
   pypy/dist/pypy/module/stackless/test/stack1.py
   pypy/dist/pypy/module/stackless/test/stack2.py
   pypy/dist/pypy/module/stackless/test/stackless_.py
Log:
this is just a version I want to get back to eventually... (Nothing exciting happend)


Modified: pypy/dist/pypy/module/stackless/test/stack1.py
==============================================================================
--- pypy/dist/pypy/module/stackless/test/stack1.py	(original)
+++ pypy/dist/pypy/module/stackless/test/stack1.py	Wed May 17 18:21:58 2006
@@ -1,17 +1,17 @@
 from stackless_ import *
 
 def f():
-    print 'in f'
+    print 'in f', getcurrent()
 
 def g(t):
-    print 'in g %s' % t
+    print 'in g %s' % t , getcurrent()
     schedule()
 
 def main():
     cg = tasklet(g)('test')
     cf = tasklet(f)()
     schedule()
-    print 'in main'
+    print 'in main', getcurrent()
 
 if __name__ == '__main__':
     main()

Modified: pypy/dist/pypy/module/stackless/test/stack2.py
==============================================================================
--- pypy/dist/pypy/module/stackless/test/stack2.py	(original)
+++ pypy/dist/pypy/module/stackless/test/stack2.py	Wed May 17 18:21:58 2006
@@ -1,20 +1,26 @@
-from stackless_ import *
+import stackless
+if hasattr(stackless,'coroutine'):
+    import stackless_ as stackless
 
 def f(outchan):
     for i in range(10):
-        print 'f send',i
+        #print 'f: outchan before:',str(outchan)
+        print 'f: sending',i
         outchan.send(i)
+        #print 'f: outchan after:',str(outchan)
     outchan.send(-1)
 
 def g(inchan):
     while 1:
+        #print 'g: inchan before:',str(inchan)
         val = inchan.receive()
+        print 'g: received',val
+        #print 'g: inchan after:',str(inchan)
         if val == -1:
             break
-        print 'g received',val
 
-ch = channel()
-t1 = tasklet(f)(ch)
-t2 = tasklet(g)(ch)
+ch = stackless.channel()
+t1 = stackless.tasklet(f)(ch)
+t2 = stackless.tasklet(g)(ch)
 
 t1.run()

Modified: pypy/dist/pypy/module/stackless/test/stackless_.py
==============================================================================
--- pypy/dist/pypy/module/stackless/test/stackless_.py	(original)
+++ pypy/dist/pypy/module/stackless/test/stackless_.py	Wed May 17 18:21:58 2006
@@ -5,6 +5,7 @@
 """
 
 from stackless import coroutine
+from collections import deque
 
 __all__ = 'run getcurrent getmain schedule tasklet channel'.split()
 
@@ -19,6 +20,27 @@
 
 This is a necessary Stackless 3.1 feature.
 """
+
+class TaskletProxy(object):
+    def __init__(self, coro):
+        self.alive = False
+        self.atomic = False
+        self.blocked = False
+        self.frame = None
+        self.ignore_nesting = False
+        self.is_current = False
+        self.is_main = False
+        self.nesting_level = 0
+        self.next = None
+        self.paused = False
+        self.prev = None
+        self.recursion_depth = 0
+        self.restorable = False
+        self.scheduled = False
+        self.thread_id = 0
+        self.tempval = None
+        self._coro = coro
+
 class bomb(object):
     """
     A bomb object is used to hold exceptions in tasklets.
@@ -42,32 +64,9 @@
     type = None
     value = None
 
-note = """
-cframes are an implementation detail.
-Do not implement this now. If we need such a thing in PyPy,
-then it will probably have a different layout.
-"""
-class cframe(object):
-    """
-    """
-    __slots__ = ['f_back','obj1','obj2','obj3','i','n']
-
 # channel: see below
 
 note = """
-The future of C stacks is undecided, yet. This applies
-for Stackless, only at the moment. PyPy will use soft-switching
-only, until we support external callbacks.
-"""
-class cstack(object):
-    """
-    A CStack object serves to save the stack slice which is involved
-    during a recursive Python call. It will also be used for pickling
-    of program state. This structure is highly platform dependant.
-    Note: For inspection, str() can dump it as a string.
-    """
-
-note = """
 I would implement it as a simple flag but let it issue
 a warning that it has no effect.
 """
@@ -103,7 +102,6 @@
 
 # def schedule(retval=stackless.current) : see below
 
-note = 'needed'
 def schedule_remove(retval=None):
     """
     schedule(retval=stackless.current) -- switch to the next runnable tasklet.
@@ -144,83 +142,19 @@
     """
     pass
 
-note = """
-this was an experiment on deriving from a module.
-The idea was to make runcount and current into properties.
-__tasklet__ and __channel__ are also not used.
-It is ok to ignore these.
-"""
-class slpmodule(object):
-    """
-    The stackless module has a special type derived from
-    the module type, in order to be able to override some attributes.
-    __tasklet__ and __channel__ are the default types
-    to be used when these objects must be instantiated internally.
-    runcount, current and main are attribute-like short-hands
-    for the getruncount, getcurrent and getmain module functions.
-    """
-
 # class tasklet: see below
 
-note = 'drop'
-def test_cframe(switches, words=0):
-    """
-    test_cframe(switches, words=0) -- a builtin testing function that does 
-    nothing but tasklet switching. The function will call 
-    PyStackless_Schedule() for switches times and then finish.
-    If words is given, as many words will be allocated on the C stack.
-    Usage: Create two tasklets for test_cframe and run them by run().
-    
-        t1 = tasklet(test_cframe)(500000)
-        t2 = tasklet(test_cframe)(500000)
-        run()
-    This can be used to measure the execution time of 1.000.000 switches.
-    """
-    pass
-
-note = 'drop'
-def test_cframe_nr(switches):
-    """
-    test_cframe_nr(switches) -- a builtin testing function that does nothing
-    but soft tasklet switching. The function will call 
-    PyStackless_Schedule_nr() for switches times and then finish.
-    Usage: Cf. test_cframe().
-    """
-    pass
-
-note = 'drop'
-def test_outside():
-    """
-    test_outside() -- a builtin testing function.
-    This function simulates an application that does not run "inside"
-    Stackless, with active, running frames, but always needs to initialize
-    the main tasklet to get "\xednside".
-    The function will terminate when no other tasklets are runnable.
-    
-    Typical usage: Create a tasklet for test_cframe and run by test_outside().
-    
-        t1 = tasklet(test_cframe)(1000000)
-        test_outside()
-
-    This can be used to measure the execution time of 1.000.000 switches.
-    """
-    pass
-
-
 # end interface
 
 main_tasklet = None
-next_tasklet = None
+main_coroutine = None
 scheduler = None
 
-coro_reg = {}
-
 def __init():
-    global maintasklet
-    mt = tasklet()
-    mt._coro = c = coroutine.getcurrent()
-    maintasklet = mt
-    coro_reg[c] = mt
+    global main_tasklet
+    global main_coroutine
+    main_coroutine = c = coroutine.getcurrent()
+    main_tasklet = TaskletProxy(c)
 
 note = """
 It is not needed to implement the watchdog feature right now.
@@ -252,8 +186,11 @@
     getcurrent() -- return the currently executing tasklet.
     """
 
-    c = coroutine.getcurrent()
-    return coro_reg[c]
+    curr = coroutine.getcurrent()
+    if curr is main_coroutine:
+        return main_tasklet
+    else:
+        return curr
 
 def getmain():
     return main_tasklet
@@ -267,17 +204,68 @@
     """
     scheduler.schedule()
 
-class tasklet(object):
+"""
+/***************************************************************************
+
+    Tasklet Flag Definition
+    -----------------------
+
+    blocked:	    The tasklet is either waiting in a channel for
+		    writing (1) or reading (-1) or not blocked (0).
+		    Maintained by the channel logic. Do not change.
+
+    atomic:	    If true, schedulers will never switch. Driven by
+		    the code object or dynamically, see below.
+
+    ignore_nesting: Allows auto-scheduling, even if nesting_level
+		    is not zero.
+
+    autoschedule:   The tasklet likes to be auto-scheduled. User driven.
+
+    block_trap:     Debugging aid. Whenever the tasklet would be
+		    blocked by a channel, an exception is raised.
+
+    is_zombie:	    This tasklet is almost dead, its deallocation has
+		    started. The tasklet *must* die at some time, or the
+		    process can never end.
+
+    pending_irq:    If set, an interrupt was issued during an atomic
+		    operation, and should be handled when possible.
+
+
+    Policy for atomic/autoschedule and switching:
+    ---------------------------------------------
+    A tasklet switch can always be done explicitly by calling schedule().
+    Atomic and schedule are concerned with automatic features.
+
+    atomic  autoschedule
+
+	1	any	Neither a scheduler nor a watchdog will
+			try to switch this tasklet.
+
+	0	0	The tasklet can be stopped on desire, or it
+			can be killed by an exception.
+
+	0	1	Like above, plus auto-scheduling is enabled.
+
+    Default settings:
+    -----------------
+    All flags are zero by default.
+
+ ***************************************************************************/
+"""
+
+class tasklet(coroutine):
     """
     A tasklet object represents a tiny task in a Python thread.
     At program start, there is always one running main tasklet.
     New tasklets can be created with methods from the stackless
     module.
     """
-#    __slots__ = ['alive','atomic','block_trap','blocked','frame',
-#                 'ignore_nesting','is_current','is_main',
-#                 'nesting_level','next','paused','prev','recursion_depth',
-#                 'restorable','scheduled','thread_id']
+    __slots__ = ['alive','atomic','blocked','frame',
+                 'ignore_nesting','is_current','is_main',
+                 'nesting_level','next','paused','prev','recursion_depth',
+                 'restorable','scheduled','tempval','thread_id']
 
     ## note: most of the above should be properties
 
@@ -289,34 +277,35 @@
     ## well, it is a design question, but fow now probably simplest
     ## to just copy that.
 
+    def __new__(cls, func=None):
+        return super(tasklet,cls).__new__(cls)
+
     def __init__(self, func=None):
-        ## note: this field should reuse tempval to save space
-        self._func = func
+        super(tasklet,self).__init__()
+        self.alive = False
+        self.atomic = False
+        self.blocked = False
+        self.frame = None
+        self.ignore_nesting = False
+        self.is_current = False
+        self.is_main = False
+        self.nesting_level = 0
+        self.next = None
+        self.paused = False
+        self.prev = None
+        self.recursion_depth = 0
+        self.restorable = False
+        self.scheduled = False
+        self.thread_id = 0
+        self.tempval = None
+        if func is not None:
+            self.bind(func)
 
     def __call__(self, *argl, **argd):
-        ## note: please inherit
-        ## note: please use spaces after comma :-)
-        ## note: please express this using bind and setup
-        self._coro = c = coroutine()
-        c.bind(self._func,*argl,**argd)
-        coro_reg[c] = self
-        self.insert()
+        self.setup(*argl, **argd)
         return self
 
-    ## note: deprecated
-    def become(self, retval=None):
-        """
-        t.become(retval) -- catch the current running frame in a tasklet.
-        It is also inserted at the end of the runnables chain.
-        If it is a toplevel frame (and therefore has no caller), an exception 
-        is raised.  The function result is the tasklet itself. retval is 
-        passed to the calling frame.
-        If retval is not given, the tasklet is used as default.
-        """
-        pass
-
-    ## note: __init__ should use this
-    def bind(self):
+    def bind(self, func):
         """
         Binding a tasklet to a callable object.
         The callable is usually passed in to the constructor.
@@ -324,19 +313,9 @@
         after it has been run, in order to keep its identity.
         Note that a tasklet can only be bound when it doesn't have a frame.
         """
-        pass
-
-    ## note: deprecated
-    def capture(self, retval=None):
-        """
-        t.capture(retval) -- capture the current running frame in a tasklet,
-        like t.become(). In addition the tasklet is run immediately, and the
-        parent tasklet is removed from the runnables and returned as the value.
-        """
-        pass
-
-    ## note: this is not part of the interface, please drop it
-    cstate = None
+        if not callable(func):
+            raise TypeError('tasklet function must be a callable')
+        self.tempval = func
 
     def insert(self):
         """
@@ -355,7 +334,7 @@
         If the exception passes the toplevel frame of the tasklet,
         the tasklet will silently die.
         """
-        pass
+        coroutine.kill(self)
 
     ## note: see the C implementation about how to use bombs
     def raise_exception(self, exc, value):
@@ -429,11 +408,36 @@
         """
         supply the parameters for the callable
         """
-        pass
+        if self.tempval is None:
+            raise TypeError('cframe function must be callable')
+        coroutine.bind(self,self.tempval,*argl,**argd)
+        self.tempval = None
+        self.insert()
+
+"""
+/***************************************************************************
+
+    Channel Flag Definition
+    -----------------------
+
 
-    ## note: this attribute should always be there.
-    ## no class default needed.
-    tempval = None
+    closing:        When the closing flag is set, the channel does not
+		    accept to be extended. The computed attribute
+		    'closed' is true when closing is set and the
+		    channel is empty.
+
+    preference:	    0    no preference, caller will continue
+		    1    sender will be inserted after receiver and run
+		    -1   receiver will be inserted after sender and run
+
+    schedule_all:   ignore preference and always schedule the next task
+
+    Default settings:
+    -----------------
+    All flags are zero by default.
+
+ ***************************************************************************/
+"""
 
 class channel(object):
     """
@@ -450,8 +454,17 @@
     def __init__(self):
         self.balance = 0
         ## note: this is a deque candidate.
-        self._readq = []
-        self._writeq = []
+        self.queue = deque()
+        self.closing = False
+        self.preference = 0
+
+    def __str__(self):
+        return 'channel(' + str(self.balance) + ' : ' + str(self.queue) + ')'
+    
+    def _get_closed(self):
+        return self.closing and not self.queue
+
+    closed = property(_get_closed)
 
     ## note: needed
     def close(self):
@@ -461,20 +474,62 @@
         If the channel is not empty, the flag 'closing' becomes true.
         If the channel is empty, the flag 'closed' becomes true.
         """
-        pass
+        self.closing = True
 
     ## note: needed. iteration over a channel reads it all.
     def next(self):
         """
         x.next() -> the next value, or raise StopIteration
         """
-        pass
+        if self.closing and not self.balance:
+            raise StopIteration()
+        return self.receive()
 
     ## note: needed
     def open(self):
         """
         channel.open() -- reopen a channel. See channel.close.
         """
+        self.closing = False
+
+    """
+    /**********************************************************
+
+      The central functions of the channel concept.
+      A tasklet can either send or receive on a channel.
+      A channel has a queue of waiting tasklets.
+      They are either all waiting to send or all
+      waiting to receive.
+      Initially, a channel is in a neutral state.
+      The queue is empty, there is no way to
+      send or receive without becoming blocked.
+
+      Sending 1):
+        A tasklet wants to send and there is
+        a queued receiving tasklet. The sender puts
+        its data into the receiver, unblocks it,
+        and inserts it at the top of the runnables.
+        The receiver is scheduled.
+      Sending 2):
+        A tasklet wants to send and there is
+        no queued receiving tasklet.
+        The sender will become blocked and inserted
+        into the queue. The next receiver will
+        handle the rest through "Receiving 1)".
+      Receiving 1):
+        A tasklet wants to receive and there is
+        a queued sending tasklet. The receiver takes
+        its data from the sender, unblocks it,
+        and inserts it at the end of the runnables.
+        The receiver continues with no switch.
+      Receiving 2):
+        A tasklet wants to receive and there is
+        no queued sending tasklet.
+        The receiver will become blocked and inserted
+        into the queue. The next sender will
+        handle the rest through "Sending 1)".
+     */
+    """
 
     def receive(self):
         """
@@ -485,17 +540,22 @@
         the runnables list.
         The above policy can be changed by setting channel flags.
         """
-        ct = getcurrent()
-        if self._writeq:
-            (wt,retval), self._writeq = self._writeq[0], self._writeq[1:]
-            scheduler.priorityinsert(wt)
+        if self.balance > 0: # Receiving 1
+            wt = self.queue.popleft()
+            retval = wt.tempval
+            wt.tempval = None
+            scheduler.insert(wt)
             self.balance -= 1
             return retval
-        else:
-            self._readq.append(ct)
+        else: # Receiving 2
+            ct = getcurrent()
             scheduler.remove(ct)
+            self.queue.append(ct)
+            self.balance -= 1
             schedule()
-            return self.receive()
+            retval = ct.tempval
+            ct.tempval = None
+            return retval
 
     def send(self, msg):
         """
@@ -506,12 +566,18 @@
         the runnables list.
         """
         ct = getcurrent()
-        scheduler.remove(ct)
-        self._writeq.append((ct,msg))
-        self.balance += 1
-        if self._readq:
-            nt, self._readq = self._readq[0], self._readq[1:]
-            scheduler.priorityinsert(nt)
+        if ct.tempval is not None:
+            print 'THERE IS STILL SOME CHANNEL SEND VALUE',ct.tempval
+        if self.balance < 0: # Sending 1
+            wt = self.queue.popleft()
+            wt.tempval = msg
+            scheduler.priorityinsert(wt)
+            self.balance += 1
+        else: # Sending 2
+            ct.tempval = msg
+            scheduler.remove(ct)
+            self.queue.append(ct)
+            self.balance += 1
         schedule()
 
     ## note: see the C implementation on how to use bombs.
@@ -549,7 +615,7 @@
         return repr(self.tasklist) + '/%s' % self.nexttask
 
     def insert(self,task):
-        if (task not in self.tasklist) and task is not maintasklet:
+        if (task not in self.tasklist) and task is not main_tasklet:
             self.tasklist.append(task)
         if self.nexttask is None:
             self.nexttask = 0
@@ -557,7 +623,7 @@
     def priorityinsert(self,task):
         if task in self.tasklist:
             self.tasklist.remove(task)
-        if task is maintasklet:
+        if task is main_tasklet:
             return
         if self.nexttask:
             self.tasklist.insert(self.nexttask,task)
@@ -583,7 +649,7 @@
                 self.nexttask = 0
             return task
         else:
-            return maintasklet
+            return main_tasklet
 
     def setnexttask(self,task):
         if task not in self.tasklist:
@@ -598,7 +664,7 @@
 
     def schedule(self):
         n = self.next()
-        n._coro.switch()
+        n.switch()
 
 scheduler = Scheduler()
 __init()


From stephan at codespeak.net  Wed May 17 21:11:07 2006
From: stephan at codespeak.net (stephan at codespeak.net)
Date: Wed, 17 May 2006 21:11:07 +0200 (CEST)
Subject: [pypy-svn] r27376 - pypy/dist/pypy/module/stackless/test
Message-ID: <20060517191107.5582C10063@code0.codespeak.net>

Author: stephan
Date: Wed May 17 21:11:05 2006
New Revision: 27376

Modified:
   pypy/dist/pypy/module/stackless/test/stackless_.py
Log:
removed explicit scheduler (will be probably reintroduced later).


Modified: pypy/dist/pypy/module/stackless/test/stackless_.py
==============================================================================
--- pypy/dist/pypy/module/stackless/test/stackless_.py	(original)
+++ pypy/dist/pypy/module/stackless/test/stackless_.py	Wed May 17 21:11:05 2006
@@ -21,6 +21,8 @@
 This is a necessary Stackless 3.1 feature.
 """
 
+last_thread_id = 0
+
 class TaskletProxy(object):
     def __init__(self, coro):
         self.alive = False
@@ -41,6 +43,12 @@
         self.tempval = None
         self._coro = coro
 
+    def __str__(self):
+        return 'Tasklet-%s' % self.thread_id
+
+    def __getattr__(self,attr):
+        return getattr(self._coro,attr)
+
 class bomb(object):
     """
     A bomb object is used to hold exceptions in tasklets.
@@ -146,15 +154,73 @@
 
 # end interface
 
+def _next():
+    c = getcurrent()
+    if c.next is c:
+        return c
+    nt = c.next
+    if nt is main_tasklet and nt.next is not c:
+        return nt.next
+    else:
+        return nt
+
+def _insert(other):
+    "put other on the end tasklet queue"
+    this = getcurrent()
+    #print '_insert:',this,
+    #_print_queue()
+    prev = this.prev
+    this.prev = other
+    other.next = this
+    other.prev = prev
+    prev.next = other
+    other.blocked = False
+
+def _priority_insert(other):
+    "other will be the next tasklet"
+    this = getcurrent()
+    #print '_priority_insert:',this,
+    #_print_queue()
+    next = this.next
+    this.next = other
+    other.prev = this
+    other.next = next
+    next.prev = other
+    other.blocked = False
+
+def _remove(this):
+    #print '_remove:',this,
+    #_print_queue()
+    if this.next is this:
+        return
+    t = c = getcurrent()
+    count = 0
+    while t is not this:
+        if t is c and count:
+            break
+        count += 1
+        t = t.next
+    this.next.prev = this.prev
+    this.prev.next = this.next
+
+def _print_queue():
+    c = s = getcurrent()
+    print '[',c,
+    while c.next is not s:
+        c = c.next
+        print c,
+    print ']'
+
 main_tasklet = None
 main_coroutine = None
-scheduler = None
 
 def __init():
     global main_tasklet
     global main_coroutine
     main_coroutine = c = coroutine.getcurrent()
     main_tasklet = TaskletProxy(c)
+    main_tasklet.next = main_tasklet.prev = main_tasklet
+    main_tasklet.is_main = True
 
 note = """
 It is not needed to implement the watchdog feature right now.
@@ -181,6 +247,7 @@
 This will create unwanted attributes, but they will
 go away when we port this to interp-leve.
 """
+
 def getcurrent():
     """
     getcurrent() -- return the currently executing tasklet.
@@ -195,14 +262,28 @@
 def getmain():
     return main_tasklet
 
-def schedule():
+def schedule(retval=None):
     """
     schedule(retval=stackless.current) -- switch to the next runnable tasklet.
     The return value for this call is retval, with the current
     tasklet as default.
     schedule_remove(retval=stackless.current) -- ditto, and remove self.
     """
-    scheduler.schedule()
+    #print 'schedule: before switch',
+    #_print_queue()
+    curr = getcurrent()
+    curr.is_current = False
+    nt = _next()
+    if curr.blocked:
+        _remove(curr)
+    nt.is_current = True
+    nt.switch()
+    #print 'schedule: after switch',
+    #_print_queue()
+    if retval is None:
+        return getcurrent()
+    else:
+        return retval
 
 """
 /***************************************************************************
@@ -281,6 +362,7 @@
         return super(tasklet,cls).__new__(cls)
 
     def __init__(self, func=None):
+        global last_thread_id
         super(tasklet,self).__init__()
         self.alive = False
         self.atomic = False
@@ -296,7 +378,8 @@
         self.recursion_depth = 0
         self.restorable = False
         self.scheduled = False
-        self.thread_id = 0
+        last_thread_id += 1
+        self.thread_id = last_thread_id
         self.tempval = None
         if func is not None:
             self.bind(func)
@@ -305,6 +388,9 @@
         self.setup(*argl, **argd)
         return self
 
+    def __str__(self):
+        return 'Tasklet-%s' % self.thread_id
+
     def bind(self, func):
         """
         Binding a tasklet to a callable object.
@@ -323,7 +409,7 @@
         given that it isn't blocked.
         Blocked tasklets need to be reactivated by channels.
         """
-        scheduler.insert(self)
+        _insert(self)
 
     ## note: this is needed. please call coroutine.kill()
     def kill(self):
@@ -354,14 +440,15 @@
         unwanted side-effects. Therefore it is recommended to either run 
         tasklets to the end or to explicitly kill() them.
         """
-        scheduler.remove(self)
+        _remove(self)
 
     def run(self):
         """
         Run this tasklet, given that it isn't blocked.
         Blocked tasks need to be reactivated by channels.
         """
-        scheduler.setnexttask(self)
+        _remove(self)
+        _priority_insert(self)
         ## note: please support different schedulers
         ## and don't mix calls to module functions with scheduler methods.
         schedule()
@@ -544,12 +631,13 @@
             wt = self.queue.popleft()
             retval = wt.tempval
             wt.tempval = None
-            scheduler.insert(wt)
+            _insert(wt)
             self.balance -= 1
             return retval
         else: # Receiving 2
             ct = getcurrent()
-            scheduler.remove(ct)
+            #_remove(ct)
+            ct.blocked = True
             self.queue.append(ct)
             self.balance -= 1
             schedule()
@@ -571,11 +659,12 @@
         if self.balance < 0: # Sending 1
             wt = self.queue.popleft()
             wt.tempval = msg
-            scheduler.priorityinsert(wt)
+            _priority_insert(wt)
             self.balance += 1
         else: # Sending 2
             ct.tempval = msg
-            scheduler.remove(ct)
+            #_remove(ct)
+            ct.blocked = True
             self.queue.append(ct)
             self.balance += 1
         schedule()
@@ -600,74 +689,5 @@
         """
         pass
 
-
-class Scheduler(object):
-    def __init__(self):
-        ## note: better use a deque
-        self.tasklist = []
-        ## note: in terms of moving to interplevel, I would not do that
-        self.nexttask = None 
-
-    def empty(self):
-        return not self.tasklist
-
-    def __str__(self):
-        return repr(self.tasklist) + '/%s' % self.nexttask
-
-    def insert(self,task):
-        if (task not in self.tasklist) and task is not main_tasklet:
-            self.tasklist.append(task)
-        if self.nexttask is None:
-            self.nexttask = 0
-
-    def priorityinsert(self,task):
-        if task in self.tasklist:
-            self.tasklist.remove(task)
-        if task is main_tasklet:
-            return
-        if self.nexttask:
-            self.tasklist.insert(self.nexttask,task)
-        else:
-            self.tasklist.insert(0,task)
-            self.nexttask = 0
-
-    def remove(self,task):
-        try:
-            i = self.tasklist.index(task)
-            del(self.tasklist[i])
-            if self.nexttask > i:
-                self.nexttask -= 1
-            if len(self.tasklist) == 0:
-                self.nexttask = None
-        except ValueError:pass
-
-    def next(self):
-        if self.nexttask is not None:
-            task = self.tasklist[self.nexttask]
-            self.nexttask += 1
-            if self.nexttask == len(self.tasklist):
-                self.nexttask = 0
-            return task
-        else:
-            return main_tasklet
-
-    def setnexttask(self,task):
-        if task not in self.tasklist:
-            self.tasklist.insert(task)
-        try:
-            ## note: this is inefficient
-            ## please use the flag attributes
-            ## a tasklet 'knows' if it is in something
-            i = self.tasklist.index(task)
-            self.nexttask = i
-        except IndexError:pass
-
-    def schedule(self):
-        n = self.next()
-        n.switch()
-
-scheduler = Scheduler()
 __init()
 
-## note: nice work :-)
-


From pedronis at codespeak.net  Wed May 17 22:59:18 2006
From: pedronis at codespeak.net (pedronis at codespeak.net)
Date: Wed, 17 May 2006 22:59:18 +0200 (CEST)
Subject: [pypy-svn] r27377 - in pypy/dist/pypy/rpython/lltypesystem: . test
Message-ID: <20060517205918.988EF10061@code0.codespeak.net>

Author: pedronis
Date: Wed May 17 22:59:17 2006
New Revision: 27377

Modified:
   pypy/dist/pypy/rpython/lltypesystem/llmemory.py
   pypy/dist/pypy/rpython/lltypesystem/test/test_llmemory.py
Log:
another test, an xxx


Modified: pypy/dist/pypy/rpython/lltypesystem/llmemory.py
==============================================================================
--- pypy/dist/pypy/rpython/lltypesystem/llmemory.py	(original)
+++ pypy/dist/pypy/rpython/lltypesystem/llmemory.py	Wed May 17 22:59:17 2006
@@ -499,8 +499,9 @@
     return size.raw_malloc([])
 
 def raw_free(adr):
+    # xxx crash if you get only the header of a gc object
     assert isinstance(adr.ob._obj, lltype._parentable)
-    adr.ob._obj._free()
+    adr.ob._as_obj()._free()
 
 def raw_malloc_usage(size):
     if isinstance(size, AddressOffset):

Modified: pypy/dist/pypy/rpython/lltypesystem/test/test_llmemory.py
==============================================================================
--- pypy/dist/pypy/rpython/lltypesystem/test/test_llmemory.py	(original)
+++ pypy/dist/pypy/rpython/lltypesystem/test/test_llmemory.py	Wed May 17 22:59:17 2006
@@ -339,7 +339,59 @@
     py.test.raises(RuntimeError, "p_u.y = 2")
     repr(adr)
     str(p_u)
+
+def test_raw_free_with_hdr():
+    from pypy.rpython.memory.gcheader import GCHeaderBuilder
+    
+    HDR = lltype.Struct('h', ('t', lltype.Signed))
+    gh = GCHeaderBuilder(HDR).size_gc_header
+    
+    A = lltype.GcArray(lltype.Signed)
+    adr = raw_malloc(gh+sizeof(A, 10))
+    p_a = cast_adr_to_ptr(adr+gh, lltype.Ptr(A))
+    p_a[0] = 1
+    adr = cast_ptr_to_adr(p_a)-gh
+    raw_free(adr)
+    py.test.raises(RuntimeError, "p_a[0]")
+    py.test.raises(RuntimeError, "p_a[0] = 2")
+    repr(adr)
+    str(p_a)
+
+    S = lltype.GcStruct('S', ('x', lltype.Signed))
+    adr = raw_malloc(gh+sizeof(S))
+    p_s = cast_adr_to_ptr(adr+gh, lltype.Ptr(S))
+    p_s.x = 1
+    adr = cast_ptr_to_adr(p_s)-gh
+    raw_free(adr)
+    py.test.raises(RuntimeError, "p_s.x")
+    py.test.raises(RuntimeError, "p_s.x = 2")
+    repr(adr)
+    str(p_s)
     
+    T = lltype.GcStruct('T', ('s', S))
+    adr = raw_malloc(gh+sizeof(T))
+    p_s = cast_adr_to_ptr(adr+gh, lltype.Ptr(S))
+    p_s.x = 1
+    adr = cast_ptr_to_adr(p_s)-gh
+    raw_free(adr)
+    py.test.raises(RuntimeError, "p_s.x")
+    py.test.raises(RuntimeError, "p_s.x = 2")
+    repr(adr)
+    str(p_s)
+    
+    U = lltype.Struct('U', ('y', lltype.Signed))
+    T = lltype.GcStruct('T', ('x', lltype.Signed), ('u', U))
+    adr = raw_malloc(gh+sizeof(T))
+    p_t = cast_adr_to_ptr(adr+gh, lltype.Ptr(T))
+    p_u = p_t.u
+    p_u.y = 1
+    adr = cast_ptr_to_adr(p_t)-gh
+    raw_free(adr)
+    py.test.raises(RuntimeError, "p_u.y")
+    py.test.raises(RuntimeError, "p_u.y = 2")
+    repr(adr)
+    str(p_u)
+
 def test_inlined_substruct():
     T = lltype.Struct('T', ('x', lltype.Signed))
     S1 = lltype.GcStruct('S1', ('t1', T), ('t2', T))


From antocuni at codespeak.net  Wed May 17 23:18:00 2006
From: antocuni at codespeak.net (antocuni at codespeak.net)
Date: Wed, 17 May 2006 23:18:00 +0200 (CEST)
Subject: [pypy-svn] r27378 - in pypy/dist/pypy/rpython: . lltypesystem
	ootypesystem test
Message-ID: <20060517211800.4BB8E10061@code0.codespeak.net>

Author: antocuni
Date: Wed May 17 23:17:44 2006
New Revision: 27378

Added:
   pypy/dist/pypy/rpython/lltypesystem/ll_str.py   (contents, props changed)
   pypy/dist/pypy/rpython/ootypesystem/ll_str.py   (contents, props changed)
Modified:
   pypy/dist/pypy/rpython/lltypesystem/rstr.py
   pypy/dist/pypy/rpython/ootypesystem/ootype.py
   pypy/dist/pypy/rpython/rint.py
   pypy/dist/pypy/rpython/test/test_rint.py
   pypy/dist/pypy/rpython/typesystem.py
Log:
Added support for int to string conversion (including hex and oct) to ootypesystem.



Added: pypy/dist/pypy/rpython/lltypesystem/ll_str.py
==============================================================================
--- (empty file)
+++ pypy/dist/pypy/rpython/lltypesystem/ll_str.py	Wed May 17 23:17:44 2006
@@ -0,0 +1,104 @@
+from pypy.rpython.lltypesystem.lltype import GcArray, Array, Char, malloc
+from pypy.rpython.rarithmetic import r_uint
+
+CHAR_ARRAY = GcArray(Char)
+
+def ll_int2dec(i):
+    from pypy.rpython.lltypesystem.rstr import STR
+    temp = malloc(CHAR_ARRAY, 20)
+    len = 0
+    sign = 0
+    if i < 0:
+        sign = 1
+        i = r_uint(-i)
+    else:
+        i = r_uint(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
+
+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.lltypesystem.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
+
+def ll_int2oct(i, addPrefix):
+    from pypy.rpython.lltypesystem.rstr import STR
+    if i == 0:
+        result = malloc(STR, 1)
+        result.chars[0] = '0'
+        return result
+    temp = malloc(CHAR_ARRAY, 25)
+    len = 0
+    sign = 0
+    if i < 0:
+        sign = 1
+        i = -i
+    while i:
+        temp[len] = hex_chars[i%8]
+        i //= 8
+        len += 1
+    len += sign
+    if addPrefix:
+        len += 1
+    result = malloc(STR, len)
+    j = 0
+    if sign:
+        result.chars[0] = '-'
+        j = 1
+    if addPrefix:
+        result.chars[j] = '0'
+        j += 1
+    while j < len:
+        result.chars[j] = temp[len-j-1]
+        j += 1
+    return result

Modified: pypy/dist/pypy/rpython/lltypesystem/rstr.py
==============================================================================
--- pypy/dist/pypy/rpython/lltypesystem/rstr.py	(original)
+++ pypy/dist/pypy/rpython/lltypesystem/rstr.py	Wed May 17 23:17:44 2006
@@ -649,9 +649,6 @@
     do_stringformat = classmethod(do_stringformat)
 
 
-
-
-
 # TODO: make the public interface of the rstr module cleaner
 ll_strconcat = LLHelpers.ll_strconcat
 ll_join = LLHelpers.ll_join
@@ -704,3 +701,5 @@
 list_str_open_bracket = string_repr.convert_const("[")
 list_str_close_bracket = string_repr.convert_const("]")
 list_str_sep = string_repr.convert_const(", ")
+
+import ll_str # side-effects due to __extend__

Added: pypy/dist/pypy/rpython/ootypesystem/ll_str.py
==============================================================================
--- (empty file)
+++ pypy/dist/pypy/rpython/ootypesystem/ll_str.py	Wed May 17 23:17:44 2006
@@ -0,0 +1,17 @@
+from pypy.rpython.ootypesystem import ootype
+
+def const(c):
+    return c
+
+def ll_int2dec(i):
+    return ootype.oostring(i, const(10))
+
+# TODO: add support for addPrefix == False
+def ll_int2hex(i, addPrefix):
+    #assert addPrefix
+    return ootype.oostring(i, const(16))
+
+def ll_int2oct(i, addPrefix):
+    #assert addPrefix
+    return ootype.oostring(i, const(8))
+

Modified: pypy/dist/pypy/rpython/ootypesystem/ootype.py
==============================================================================
--- pypy/dist/pypy/rpython/ootypesystem/ootype.py	(original)
+++ pypy/dist/pypy/rpython/ootypesystem/ootype.py	Wed May 17 23:17:44 2006
@@ -1169,8 +1169,8 @@
     """
     if isinstance(obj, int):
         assert base in (-1, 8, 10, 16)
-        fmt = {-1:'%d', 8:'%o', 10:'%d', 16:'%x'}[base]
-        obj = fmt % obj
+        fn = {-1: str, 8: oct, 10: str, 16: hex}[base]
+        obj = fn(obj)
     elif isinstance(obj, _view):
         obj = '<%s object>' % obj._inst._TYPE._name
     return make_string(str(obj))

Modified: pypy/dist/pypy/rpython/rint.py
==============================================================================
--- pypy/dist/pypy/rpython/rint.py	(original)
+++ pypy/dist/pypy/rpython/rint.py	Wed May 17 23:17:44 2006
@@ -3,9 +3,8 @@
 from pypy.annotation import model as annmodel
 from pypy.objspace.flow.objspace import op_appendices
 from pypy.rpython.lltypesystem.lltype import Signed, Unsigned, Bool, Float, \
-     Void, Char, UniChar, GcArray, malloc, Array, pyobjectptr, \
-     UnsignedLongLong, SignedLongLong, build_number, Number, cast_primitive, \
-     typeOf
+     Void, Char, UniChar, malloc, pyobjectptr, UnsignedLongLong, \
+     SignedLongLong, build_number, Number, cast_primitive, typeOf
 from pypy.rpython.rmodel import IntegerRepr, inputconst
 from pypy.rpython.robject import PyObjRepr, pyobj_repr
 from pypy.rpython.rarithmetic import intmask, r_int, r_uint, r_ulonglong, r_longlong
@@ -299,121 +298,23 @@
         vlist = hop.inputargs(Float)
         return vlist[0]
 
-    def ll_str(self, i):
-        from pypy.rpython.lltypesystem.rstr import STR
-        temp = malloc(CHAR_ARRAY, 20)
-        len = 0
-        sign = 0
-        if i < 0:
-            sign = 1
-            i = r_uint(-i)
-        else:
-            i = r_uint(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
+    def rtype_str(self, hop):
+        fn = hop.rtyper.type_system.ll_str.ll_int2dec
+        return hop.gendirectcall(fn, hop.args_v[0])
 
     def rtype_hex(self, hop):
         self = self.as_int
         varg = hop.inputarg(self, 0)
         true = inputconst(Bool, True)
-        return hop.gendirectcall(ll_int2hex, varg, true)
+        fn = hop.rtyper.type_system.ll_str.ll_int2hex
+        return hop.gendirectcall(fn, varg, true)
 
     def rtype_oct(self, hop):
         self = self.as_int
         varg = hop.inputarg(self, 0)
         true = inputconst(Bool, True)
-        return hop.gendirectcall(ll_int2oct, varg, true)
-
-
-
-CHAR_ARRAY = GcArray(Char)
-
-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.lltypesystem.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
-
-def ll_int2oct(i, addPrefix):
-    from pypy.rpython.lltypesystem.rstr import STR
-    if i == 0:
-        result = malloc(STR, 1)
-        result.chars[0] = '0'
-        return result
-    temp = malloc(CHAR_ARRAY, 25)
-    len = 0
-    sign = 0
-    if i < 0:
-        sign = 1
-        i = -i
-    while i:
-        temp[len] = hex_chars[i%8]
-        i //= 8
-        len += 1
-    len += sign
-    if addPrefix:
-        len += 1
-    result = malloc(STR, len)
-    j = 0
-    if sign:
-        result.chars[0] = '-'
-        j = 1
-    if addPrefix:
-        result.chars[j] = '0'
-        j += 1
-    while j < len:
-        result.chars[j] = temp[len-j-1]
-        j += 1
-    return result
+        fn = hop.rtyper.type_system.ll_str.ll_int2oct        
+        return hop.gendirectcall(fn, varg, true)
 
 def ll_identity(n):
     return n

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	Wed May 17 23:17:44 2006
@@ -4,7 +4,7 @@
 from pypy.rpython.test import snippet
 from pypy.rpython.test.test_llinterp import interpret
 from pypy.rpython.rarithmetic import r_uint, r_longlong, r_ulonglong
-
+from pypy.rpython.test.tool import BaseRtypingTest, LLRtypeMixin, OORtypeMixin
 
 class TestSnippet(object):
 
@@ -37,58 +37,6 @@
             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'
-    
-def test_str_of_int():
-    def dummy(i):
-        return str(i)
-    
-    res = interpret(dummy, [0])
-    assert ''.join(res.chars) == '0'
-
-    res = interpret(dummy, [1034])
-    assert ''.join(res.chars) == '1034'
-
-    res = interpret(dummy, [-123])
-    assert ''.join(res.chars) == '-123'
-
-    res = interpret(dummy, [-sys.maxint-1])
-    assert ''.join(res.chars) == str(-sys.maxint-1)
-
-def test_hex_of_int():
-    def dummy(i):
-        return hex(i)
-    
-    res = interpret(dummy, [0])
-    assert ''.join(res.chars) == '0x0'
-
-    res = interpret(dummy, [1034])
-    assert ''.join(res.chars) == '0x40a'
-
-    res = interpret(dummy, [-123])
-    assert ''.join(res.chars) == '-0x7b'
-
-def test_oct_of_int():
-    def dummy(i):
-        return oct(i)
-    
-    res = interpret(dummy, [0])
-    assert ''.join(res.chars) == '0'
-
-    res = interpret(dummy, [1034])
-    assert ''.join(res.chars) == '02012'
-
-    res = interpret(dummy, [-123])
-    assert ''.join(res.chars) == '-0173'
-
 def test_unsigned():
     def dummy(i):
         i = r_uint(i)
@@ -172,3 +120,65 @@
         res = interpret(f, [inttype(0)])
         assert res == f(inttype(0))
         assert type(res) == inttype
+
+
+class BaseTestRint(BaseRtypingTest):
+    
+    def test_char_constant(self):
+        def dummyfn(i):
+            return chr(i)
+        res = self.interpret(dummyfn, [ord(' ')])
+        assert res == ' '
+        res = self.interpret(dummyfn, [0])
+        assert res == '\0'
+        res = self.interpret(dummyfn, [ord('a')])
+        assert res == 'a'
+
+    def test_str_of_int(self):
+        def dummy(i):
+            return str(i)
+
+        res = self.interpret(dummy, [0])
+        assert self.ll_to_string(res) == '0'
+
+        res = self.interpret(dummy, [1034])
+        assert self.ll_to_string(res) == '1034'
+
+        res = self.interpret(dummy, [-123])
+        assert self.ll_to_string(res) == '-123'
+
+        res = self.interpret(dummy, [-sys.maxint-1])
+        assert self.ll_to_string(res) == str(-sys.maxint-1)
+
+    def test_hex_of_int(self):
+        def dummy(i):
+            return hex(i)
+
+        res = self.interpret(dummy, [0])
+        assert self.ll_to_string(res) == '0x0'
+
+        res = self.interpret(dummy, [1034])
+        assert self.ll_to_string(res) == '0x40a'
+
+        res = self.interpret(dummy, [-123])
+        assert self.ll_to_string(res) == '-0x7b'
+
+    def test_oct_of_int(self):
+        def dummy(i):
+            return oct(i)
+
+        res = self.interpret(dummy, [0])
+        assert self.ll_to_string(res) == '0'
+
+        res = self.interpret(dummy, [1034])
+        assert self.ll_to_string(res) == '02012'
+
+        res = self.interpret(dummy, [-123])
+        assert self.ll_to_string(res) == '-0173'
+
+
+class TestLLtype(BaseTestRint, LLRtypeMixin):
+    pass
+
+class TestOOtype(BaseTestRint, OORtypeMixin):
+    pass

Modified: pypy/dist/pypy/rpython/typesystem.py
==============================================================================
--- pypy/dist/pypy/rpython/typesystem.py	(original)
+++ pypy/dist/pypy/rpython/typesystem.py	Wed May 17 23:17:44 2006
@@ -21,7 +21,7 @@
             except ImportError:
                 return None
         if name in ('rclass', 'rpbc', 'rbuiltin', 'rtuple', 'rlist',
-                'rslice', 'rdict', 'rrange', 'rstr', 'exceptiondata'):
+                'rslice', 'rdict', 'rrange', 'rstr', 'll_str', 'exceptiondata'):
             mod = load(name)
             if mod is not None:
                 setattr(self, name, mod)


From ac at codespeak.net  Thu May 18 00:20:42 2006
From: ac at codespeak.net (ac at codespeak.net)
Date: Thu, 18 May 2006 00:20:42 +0200 (CEST)
Subject: [pypy-svn] r27379 - pypy/dist/pypy/module/select
Message-ID: <20060517222042.1F29910061@code0.codespeak.net>

Author: ac
Date: Thu May 18 00:20:42 2006
New Revision: 27379

Added:
   pypy/dist/pypy/module/select/   (props changed)
   pypy/dist/pypy/module/select/__init__.py   (contents, props changed)
   pypy/dist/pypy/module/select/app_select.py   (contents, props changed)
   pypy/dist/pypy/module/select/conftest.py   (contents, props changed)
   pypy/dist/pypy/module/select/ctypes_select.py   (contents, props changed)
   pypy/dist/pypy/module/select/interp_select.py   (contents, props changed)
Log:
First cut at select module, but cheating.
select is implemented by using poll.



Added: pypy/dist/pypy/module/select/__init__.py
==============================================================================
--- (empty file)
+++ pypy/dist/pypy/module/select/__init__.py	Thu May 18 00:20:42 2006
@@ -0,0 +1,21 @@
+# Package initialisation
+from pypy.interpreter.mixedmodule import MixedModule
+import sys
+
+class Module(MixedModule):
+    appleveldefs = {
+        'error': 'app_select.error',
+        'select': 'app_select.select',
+    }
+
+    interpleveldefs = {
+        'poll'  :  'interp_select.poll',
+    }
+
+    def buildloaders(cls):
+        from pypy.module.select import ctypes_select as _c 
+        for constant, value in _c.constants.iteritems():
+            Module.interpleveldefs[constant] = "space.wrap(%r)" % value
+        super(Module, cls).buildloaders()
+    buildloaders = classmethod(buildloaders)
+

Added: pypy/dist/pypy/module/select/app_select.py
==============================================================================
--- (empty file)
+++ pypy/dist/pypy/module/select/app_select.py	Thu May 18 00:20:42 2006
@@ -0,0 +1,48 @@
+class error(Exception):
+    pass
+
+def as_fd(f):
+    if not isinstance(f, (int, long)):
+        try:
+            fileno = f.fileno
+        except AttributeError:
+            raise TypeError("argument must be an int, or have a fileno() method.")
+        f = f.fileno()
+        if not isinstance(f, (int, long)):
+            raise TypeError("fileno() returned a non-integer")
+    fd = int(f)
+    if fd < 0 or isinstance(fd, long):
+        raise ValueError("file descriptor cannot be a negative integer (%i)"%fd)
+    return fd
+
+def select(iwtd, owtd, ewtd, timeout=None):
+    from select import poll, POLLIN, POLLOUT, POLLPRI
+    fddict = {}
+    polldict = {}
+    fd = 0
+    for f in iwtd + owtd + ewtd:
+        fddict[id(f)] = as_fd(f)
+    for f in iwtd:
+        fd = fddict[id(f)]
+        polldict[fd] = polldict.get(fd, 0) | POLLIN
+    for f in owtd:
+        fd = fddict[id(f)]
+        polldict[fd] = polldict.get(fd, 0) | POLLOUT
+    for f in ewtd:
+        fd = fddict[id(f)]
+        polldict[fd] = polldict.get(fd, 0) | POLLPRI
+
+    p = poll()
+    for fd, mask in polldict.iteritems():
+        p.register(fd, mask)
+    if timeout is not None:
+        ret = dict(p.poll(int(timeout * 1000)))
+    else:
+        ret = dict(p.poll())
+
+    iretd = [ f for f in iwtd if ret.get(fddict[id(f)], 0) & POLLIN]
+    oretd = [ f for f in owtd if ret.get(fddict[id(f)], 0) & POLLOUT]
+    eretd = [ f for f in ewtd if ret.get(fddict[id(f)], 0) & POLLPRI]
+
+    return iretd, oretd, eretd
+    

Added: pypy/dist/pypy/module/select/conftest.py
==============================================================================
--- (empty file)
+++ pypy/dist/pypy/module/select/conftest.py	Thu May 18 00:20:42 2006
@@ -0,0 +1,10 @@
+import py
+
+class Directory(py.test.collect.Directory):
+
+    def run(self):
+        try:
+            import ctypes
+        except ImportError:
+            py.test.skip("these tests need ctypes installed")
+        return super(Directory, self).run()

Added: pypy/dist/pypy/module/select/ctypes_select.py
==============================================================================
--- (empty file)
+++ pypy/dist/pypy/module/select/ctypes_select.py	Thu May 18 00:20:42 2006
@@ -0,0 +1,37 @@
+from pypy.rpython.rctypes.tool import ctypes_platform
+from ctypes import *
+from pypy.rpython.rctypes.tool import util      # ctypes.util from 0.9.9.6
+
+includes = ('sys/poll.h',
+            'sys/select.h',
+            )
+constant_names = '''POLLIN POLLPRI POLLOUT POLLERR POLLHUP POLLNVAL
+    POLLRDNORM POLLRDBAND POLLWRNORM POLLWEBAND POLLMSG'''.split()
+
+class CConfig:
+    _header_ = ''.join(['#include <%s>\n' % filename for filename in includes])
+    locals().update(map(lambda name: (name, ctypes_platform.DefinedConstantInteger(name)), constant_names))
+    nfds_t = ctypes_platform.SimpleType('nfds_t')
+    pollfd = ctypes_platform.Struct('struct pollfd',
+                                    [('fd', c_int),
+                                     ('events', c_short),
+                                     ('revents', c_short)])
+    
+globals().update(ctypes_platform.configure(CConfig))
+constants = {}
+for name in constant_names:
+    value = globals()[name]
+    if value is not None:
+        constants[name] = value
+        
+dllname = util.find_library('c')
+assert dllname is not None
+libc = cdll.LoadLibrary(dllname)
+
+poll = libc.poll
+poll.argtypes = [POINTER(pollfd), nfds_t, c_int]
+poll.restype = c_int
+
+strerror = libc.strerror
+strerror.argtypes = [c_int]
+strerror.restype = c_char_p

Added: pypy/dist/pypy/module/select/interp_select.py
==============================================================================
--- (empty file)
+++ pypy/dist/pypy/module/select/interp_select.py	Thu May 18 00:20:42 2006
@@ -0,0 +1,96 @@
+from pypy.interpreter.typedef import TypeDef
+from pypy.interpreter.baseobjspace import Wrappable
+from pypy.interpreter.gateway import W_Root, ObjSpace, interp2app
+from pypy.module.select import ctypes_select as _c
+from pypy.rpython.rctypes.aerrno import geterrno
+from pypy.interpreter.error import OperationError
+
+defaultevents = _c.POLLIN | _c.POLLOUT | _c.POLLPRI
+
+def poll(space):
+    return Poll()
+
+def as_fd_w(space, w_fd):
+    if not space.is_true(space.isinstance(w_fd, space.w_int)):
+        try:
+            w_fileno = space.getattr(w_fd, space.wrap('fileno'))
+        except OperationError, e:
+            if e.match(space, space.w_AttributeError):
+                raise OperationError(space.w_TypeError,
+                                     space.wrap("argument must be an int, or have a fileno() method."))
+            raise
+        w_fd = space.call_function(w_fileno)
+        if not space.is_true(space.isinstance(w_fd, space.w_int)):
+            raise OperationError(space.w_TypeError,
+                                 space.wrap('filneo() return a non-integer'))
+        
+    fd = space.int_w(w_fd)
+    if fd < 0:
+        raise OperationError(space.w_ValueError,
+                             space.wrap("file descriptor cannot be a negative integer (%d)"%fd))
+    return fd
+
+class Poll(Wrappable):
+    def __init__(self):
+        self.fddict = {}
+
+    def register(self, space, w_fd, events=defaultevents):
+        fd = as_fd_w(space, w_fd)
+        self.fddict[fd] = events
+    register.unwrap_spec = ['self', ObjSpace, W_Root, int]
+
+    def unregister(self, space, w_fd):
+        fd = as_fd_w(space, w_fd)
+        try:
+            del self.fddict[fd]
+        except KeyError:
+            raise OperationError(space.w_KeyError,
+                                 space.wrap(fd))
+    unregister.unwrap_spec = ['self', ObjSpace, W_Root]
+
+    def poll(self, space, w_timeout=None):
+        if space.is_w(w_timeout, space.w_None):
+            timeout = -1
+        else:
+            timeout = space.int_w(w_timeout)
+            
+        numfd = len(self.fddict)
+        buf = _c.create_string_buffer(_c.sizeof(_c.pollfd) * numfd)
+        pollfds = _c.cast(buf, _c.POINTER(_c.pollfd))
+        i = 0
+        for fd, events in self.fddict.iteritems():
+            pollfds[i].fd = fd
+            pollfds[i].events = events
+            i += 1
+
+        # XXX Temporary hack for releasing the GIL
+        GIL = space.threadlocals.getGIL()
+        if GIL is not None: GIL.release()
+        ret = _c.poll(pollfds, numfd, timeout)
+        if GIL is not None: GIL.acquire(True)
+
+        if ret < 0:
+            errno = geterrno()
+            w_module = space.getbuiltinmodule('select')
+            w_errortype = space.getattr(w_module, space.wrap('error'))
+            message = _c.strerror(errno)
+            raise OperationError(w_errortype,
+                                 space.newtuple([space.wrap(errno),
+                                                 space.wrap(message)]))
+        
+        retval_w = []
+        for i in range(numfd):
+            pollfd = pollfds[i]
+            if pollfd.revents:
+                retval_w.append(space.newtuple([space.wrap(pollfd.fd),
+                                                space.wrap(pollfd.revents)]))
+        return space.newlist(retval_w)
+    poll.unwrap_spec = ['self', ObjSpace, W_Root]
+
+pollmethods = {}
+for methodname in 'register unregister poll'.split():
+    method = getattr(Poll, methodname)
+    assert hasattr(method,'unwrap_spec'), methodname
+    assert method.im_func.func_code.co_argcount == len(method.unwrap_spec), methodname
+    pollmethods[methodname] = interp2app(method, unwrap_spec=method.unwrap_spec)
+Poll.typedef = TypeDef('select.poll', **pollmethods)


From pedronis at codespeak.net  Thu May 18 02:12:15 2006
From: pedronis at codespeak.net (pedronis at codespeak.net)
Date: Thu, 18 May 2006 02:12:15 +0200 (CEST)
Subject: [pypy-svn] r27380 - in pypy/dist/pypy/rpython/memory: . test
Message-ID: <20060518001215.4B34510063@code0.codespeak.net>

Author: pedronis
Date: Thu May 18 02:12:13 2006
New Revision: 27380

Modified:
   pypy/dist/pypy/rpython/memory/gc.py
   pypy/dist/pypy/rpython/memory/gcheader.py
   pypy/dist/pypy/rpython/memory/gclltype.py
   pypy/dist/pypy/rpython/memory/gcwrapper.py
   pypy/dist/pypy/rpython/memory/test/test_gc.py
   pypy/dist/pypy/rpython/memory/test/test_transformed_gc.py
Log:
ah ah. too funny.

started working on making the semispace gc tested with the transformer. tried to use test_gc to see
if I broke something. there were some perplexing problems, discovered that the maze of setup and teardown
in test_gc made it so that mark and sweep was not tested by it at all anymore and it shared some
of the tweaked semispace problems. ah ah, that's why no prints.
of course mark and sweep was broken in test_gc: gcwrapper trying to annotate the __init__ which is not rpython
anymore, to shallow typos, to the os.write and strings requiring in theory that the gc function graphs
be converted too.

after quite a bit of pushing and pulling test_gc is testing successfully mark and sweep again. 
Of course accumulated more reasons for wanting to kill it and gcwrapper.

ah ah. too funny. not much progress on the semispace transformer testing tough :(



Modified: pypy/dist/pypy/rpython/memory/gc.py
==============================================================================
--- pypy/dist/pypy/rpython/memory/gc.py	(original)
+++ pypy/dist/pypy/rpython/memory/gc.py	Thu May 18 02:12:13 2006
@@ -15,9 +15,8 @@
 class GCError(Exception):
     pass
 
-def get_dummy_annotate(gc_class, AddressLinkedList):
+def get_dummy_annotate(gc, AddressLinkedList):
     def dummy_annotate():
-        gc = gc_class(AddressLinkedList)
         gc.setup()
         gc.get_roots = dummy_get_roots1 #prevent the get_roots attribute to 
         gc.get_roots = dummy_get_roots2 #be constants
@@ -99,7 +98,8 @@
     def init_gc_object(self, addr, typeid):
         return
     init_gc_object_immortal = init_gc_object
-   
+
+DEBUG_PRINT = True
 
 class MarkSweepGC(GCBase):
     _alloc_flavor_ = "raw"
@@ -133,7 +133,7 @@
             ref = self.malloc_fixedsize(typeid, size, True)
         # XXX lots of cast and reverse-cast around, but this malloc()
         # should eventually be killed
-        return lltype.cast_ptr_to_adr(ref)
+        return llmemory.cast_ptr_to_adr(ref)
 
     def malloc_fixedsize(self, typeid, size, can_collect):
         if can_collect and self.bytes_malloced > self.bytes_malloced_threshold:
@@ -171,7 +171,8 @@
 
     def collect(self):
         import os, time
-        os.write(2, 'collecting...\n')
+        if DEBUG_PRINT:
+            os.write(2, 'collecting...\n')
         start_time = time.time()
         roots = self.get_roots()
         size_gc_header = self.gcheaderbuilder.size_gc_header
@@ -253,16 +254,17 @@
         self.total_collection_time += end_time - start_time
         # warning, the following debug print allocates memory to manipulate
         # the strings!  so it must be at the end
-        os.write(2, "  malloced since previous collection: %s bytes\n" %
-                 old_malloced)
-        os.write(2, "  heap usage at start of collection:  %s bytes\n" %
-                 (self.heap_usage + old_malloced))
-        os.write(2, "  freed:                              %s bytes\n" %
-                 freed_size)
-        os.write(2, "  new heap usage:                     %s bytes\n" %
-                 curr_heap_size)
-        os.write(2, "  total time spent collecting:        %s seconds\n" %
-                 self.total_collection_time)
+        if DEBUG_PRINT:
+            os.write(2, "  malloced since previous collection: %s bytes\n" %
+                     old_malloced)
+            os.write(2, "  heap usage at start of collection:  %s bytes\n" %
+                     (self.heap_usage + old_malloced))
+            os.write(2, "  freed:                              %s bytes\n" %
+                     freed_size)
+            os.write(2, "  new heap usage:                     %s bytes\n" %
+                     curr_heap_size)
+            os.write(2, "  total time spent collecting:        %s seconds\n" %
+                     self.total_collection_time)
         assert self.heap_usage + old_malloced == curr_heap_size + freed_size
         self.heap_usage = curr_heap_size
 
@@ -282,6 +284,9 @@
 class SemiSpaceGC(GCBase):
     _alloc_flavor_ = "raw"
 
+    HDR = lltype.Struct('header', ('forw', lltype.Signed),
+                                  ('typeid', lltype.Signed))
+
     def __init__(self, AddressLinkedList, space_size=1024*int_size,
                  get_roots=None):
         self.bytes_malloced = 0
@@ -291,6 +296,7 @@
         self.fromspace = NULL
         self.free = NULL
         self.get_roots = get_roots
+        self.gcheaderbuilder = GCHeaderBuilder(self.HDR)
 
     def setup(self):
         self.tospace = raw_malloc(self.space_size)
@@ -308,9 +314,20 @@
     def malloc(self, typeid, length=0):
         size = self.fixed_size(typeid)
         if self.is_varsize(typeid):
-            size += length * self.varsize_item_sizes(typeid)
-        totalsize = size + self.size_gc_header()
-        if self.free + totalsize > self.top_of_space:
+            itemsize = self.varsize_item_sizes(typeid)
+            offset_to_length = self.varsize_offset_to_length(typeid)
+            ref = self.malloc_varsize(typeid, length, size, itemsize,
+                                      offset_to_length, True)
+        else:
+            ref = self.malloc_fixedsize(typeid, size, True)
+        # XXX lots of cast and reverse-cast around, but this malloc()
+        # should eventually be killed
+        return llmemory.cast_ptr_to_adr(ref)
+    
+    def malloc_fixedsize(self, typeid, size, can_collect):
+        size_gc_header = self.gcheaderbuilder.size_gc_header
+        totalsize = size_gc_header + size
+        if can_collect and self.free + totalsize > self.top_of_space:
             self.collect()
             #XXX need to increase the space size if the object is too big
             #for bonus points do big objects differently
@@ -318,9 +335,30 @@
                 raise MemoryError
         result = self.free
         self.init_gc_object(result, typeid)
-##         print "mallocing %s, size %s at %s" % (typeid, size, result)
         self.free += totalsize
-        return result + self.size_gc_header()
+        return llmemory.cast_adr_to_ptr(result+size_gc_header, llmemory.GCREF)
+
+    def malloc_varsize(self, typeid, length, size, itemsize, offset_to_length,
+                       can_collect):
+        try:
+            varsize = rarithmetic.ovfcheck(itemsize * length)
+        except OverflowError:
+            raise MemoryError
+        # XXX also check for overflow on the various '+' below!
+        size += varsize
+        size_gc_header = self.gcheaderbuilder.size_gc_header
+        totalsize = size_gc_header + size
+        if can_collect and self.free + totalsize > self.top_of_space:
+            self.collect()
+            #XXX need to increase the space size if the object is too big
+            #for bonus points do big objects differently
+            if self.free + totalsize > self.top_of_space:
+                raise MemoryError
+        result = self.free
+        self.init_gc_object(result, typeid)
+        (result + size_gc_header + offset_to_length).signed[0] = length
+        self.free += totalsize
+        return llmemory.cast_adr_to_ptr(result+size_gc_header, llmemory.GCREF)
 
     def collect(self):
 ##         print "collecting"
@@ -414,9 +452,8 @@
             size += length * self.varsize_item_sizes(typeid)
         return size
 
-
     def size_gc_header(self, typeid=0):
-        return gc_header_two_ints
+        return self.gcheaderbuilder.size_gc_header
 
     def init_gc_object(self, addr, typeid):
         addr.signed[0] = 0

Modified: pypy/dist/pypy/rpython/memory/gcheader.py
==============================================================================
--- pypy/dist/pypy/rpython/memory/gcheader.py	(original)
+++ pypy/dist/pypy/rpython/memory/gcheader.py	Thu May 18 02:12:13 2006
@@ -5,6 +5,7 @@
 class GCHeaderBuilder(object):
 
     def __init__(self, HDR):
+        """NOT_RPYTHON"""
         self.HDR = HDR
         self.obj2header = weakref.WeakKeyDictionary()
         self.header2obj = weakref.WeakKeyDictionary()

Modified: pypy/dist/pypy/rpython/memory/gclltype.py
==============================================================================
--- pypy/dist/pypy/rpython/memory/gclltype.py	(original)
+++ pypy/dist/pypy/rpython/memory/gclltype.py	Thu May 18 02:12:13 2006
@@ -5,6 +5,9 @@
 from pypy.rpython.memory.lltypesimulation import pyobjectptr
 from pypy.rpython.memory.lladdress import raw_malloc, raw_free, raw_memcopy
 
+def raw_malloc_usage(sz):
+    return sz
+
 def notimplemented(*args, **kwargs):
     raise NotImplemented
 

Modified: pypy/dist/pypy/rpython/memory/gcwrapper.py
==============================================================================
--- pypy/dist/pypy/rpython/memory/gcwrapper.py	(original)
+++ pypy/dist/pypy/rpython/memory/gcwrapper.py	Thu May 18 02:12:13 2006
@@ -13,8 +13,10 @@
         self.types = []
         self.type_to_typeid = {}
 
-    def get_typeid(self, TYPE):
+    def get_typeid(self, TYPE, nonewtype=False):
         if TYPE not in self.type_to_typeid:
+            if nonewtype:
+                raise Exception, "unknown type: %s" % TYPE
             index = len(self.types)
             self.type_to_typeid[TYPE] = index
             self.types.append(TYPE)
@@ -23,6 +25,7 @@
         return typeid
 
     def create_query_functions(self):
+        from pypy.rpython.lltypesystem import rstr
         _is_varsize = []
         _offsets_to_gc_pointers = []
         _fixed_size = []
@@ -193,7 +196,7 @@
 
 
     def get_arg_malloc(self, TYPE, size=0):
-        typeid = self.query_types.get_typeid(TYPE)
+        typeid = self.query_types.get_typeid(TYPE, nonewtype=True)
         return [typeid, size]
 
     def get_funcptr_malloc(self):
@@ -274,13 +277,13 @@
         def instantiate_linked_list():
             return AddressLinkedList()
         f1, f2, f3, f4, f5, f6, f7 = self.query_types.create_query_functions()
+        the_gc = gc_class(AddressLinkedList)
         def instantiate_gc():
-            gc = gc_class(AddressLinkedList)
-            gc.set_query_functions(f1, f2, f3, f4, f5, f6, f7)
-            gc.setup()
-            return gc
+            the_gc.set_query_functions(f1, f2, f3, f4, f5, f6, f7)
+            the_gc.setup()
+            return the_gc
         func, dummy_get_roots1, dummy_get_roots2 = gc.get_dummy_annotate(
-            self.gc.__class__, self.AddressLinkedList)
+            the_gc, self.AddressLinkedList)
         self.gc.get_roots = dummy_get_roots1
         a = RPythonAnnotator()
         a.build_types(instantiate_gc, [])
@@ -316,7 +319,7 @@
 ##         a.translator.view()
 
     def get_arg_malloc(self, TYPE, size=0):
-        typeid = self.query_types.get_typeid(TYPE)
+        typeid = self.query_types.get_typeid(TYPE, nonewtype=True)
         return [self.gcptr, typeid, size]
 
     def get_funcptr_malloc(self):

Modified: pypy/dist/pypy/rpython/memory/test/test_gc.py
==============================================================================
--- pypy/dist/pypy/rpython/memory/test/test_gc.py	(original)
+++ pypy/dist/pypy/rpython/memory/test/test_gc.py	Thu May 18 02:12:13 2006
@@ -25,20 +25,21 @@
     py.log.setconsumer("llinterp", py.log.STDOUT)
     py.log.setconsumer("llinterp frame", stdout_ignore_ll_functions)
     py.log.setconsumer("llinterp operation", None)
-    gclltype.prepare_graphs_and_create_gc = gclltype.create_gc
 
-def teardown_module(mod):
-    gclltype.prepare_graphs_and_create_gc = gclltype.create_no_gc
 
-class TestMarkSweepGC(object):
-    def setup_class(cls):
-        cls.prep_old = gclltype.prepare_graphs_and_create_gc
-        cls.old = gclltype.use_gc
-        gclltype.use_gc = MarkSweepGC
+class GCTest(object):
 
+    def setup_class(cls):
+        gclltype.prepare_graphs_and_create_gc = gclltype.create_gc
+        gclltype.use_gc = cls.GCClass
+        from pypy.rpython.memory import gc as gcimpl
+        gcimpl.DEBUG_PRINT = False
+        
     def teardown_class(cls):
-        gclltype.prepare_graphs_and_create_gc = cls.prep_old.im_func
-        gclltype.use_gc = cls.old
+        gclltype.prepare_graphs_and_create_gc =  gclltype.create_no_gc
+        gclltype.use_gc = MarkSweepGC
+        from pypy.rpython.memory import gc as gcimpl
+        gcimpl.DEBUG_PRINT = True
 
     def test_llinterp_lists(self):
         curr = simulator.current_size
@@ -93,65 +94,30 @@
         assert res == concat(100)
         assert simulator.current_size - curr < 16000 * INT_SIZE / 4
 
-class TestMarkSweepGCRunningOnLLinterp(TestMarkSweepGC):
-    def setup_class(cls):
-        cls.prep_old = gclltype.prepare_graphs_and_create_gc
-        gclltype.prepare_graphs_and_create_gc = gclltype.create_gc_run_on_llinterp
-    def teardown_class(cls):
-        gclltype.prepare_graphs_and_create_gc = cls.prep_old.im_func
 
-class TestSemiSpaceGC(TestMarkSweepGC):
-    def setup_class(cls):
-        gclltype.use_gc = SemiSpaceGC
-        cls.old = gclltype.use_gc
-    def teardown_class(cls):
-        gclltype.use_gc = cls.old
+class GCTestOnLLInterp(GCTest):
 
-class TestSemiSpaceGCRunningOnLLinterp(TestMarkSweepGC):
     def setup_class(cls):
-        cls.prep_old = gclltype.prepare_graphs_and_create_gc
         gclltype.prepare_graphs_and_create_gc = gclltype.create_gc_run_on_llinterp
-        gclltype.use_gc = SemiSpaceGC
-        cls.old = gclltype.use_gc
-
-    def teardown_class(cls):
-        gclltype.prepare_graphs_and_create_gc = cls.prep_old.im_func
-        gclltype.use_gc = cls.old
+        gclltype.use_gc = cls.GCClass
+        from pypy.rpython.memory import gc as gcimpl
+        gcimpl.DEBUG_PRINT = False
 
-class TestDeferredRefcountingGC(TestMarkSweepGC):
-    def setup_class(cls):
-        gclltype.use_gc = DeferredRefcountingGC
-        cls.old = gclltype.use_gc
-    def teardown_class(cls):
-        gclltype.use_gc = cls.old
+class TestMarkSweepGC(GCTest):
+    GCClass = MarkSweepGC
 
+class TestMarkSweepGCRunningOnLLinterp(GCTestOnLLInterp):
+    GCClass = MarkSweepGC
 
-class TestDeferredRefcountingGCRunningOnLLinterp(TestMarkSweepGC):
-    def setup_class(cls):
-        cls.prep_old = gclltype.prepare_graphs_and_create_gc
-        gclltype.prepare_graphs_and_create_gc = gclltype.create_gc_run_on_llinterp
-        gclltype.use_gc = DeferredRefcountingGC
-        cls.old = gclltype.use_gc
+class TestSemiSpaceGC(GCTest):
+    GCClass = SemiSpaceGC
 
-    def teardown_class(cls):
-        gclltype.prepare_graphs_and_create_gc = cls.prep_old.im_func
-        gclltype.use_gc = cls.old
+class TestSemiSpaceGCRunningOnLLinterp(GCTestOnLLInterp):
+    GCClass = SemiSpaceGC
 
-class TestDummyGC(TestMarkSweepGC):
-    def setup_class(cls):
-        gclltype.use_gc = DummyGC
-        cls.old = gclltype.use_gc
-    def teardown_class(cls):
-        gclltype.use_gc = cls.old
+class TestDeferredRefcountingGC(GCTest):
+    GCClass = DeferredRefcountingGC
 
-class TestDummyGCRunningOnLLinterp(TestMarkSweepGC):
-    def setup_class(cls):
-        cls.prep_old = gclltype.prepare_graphs_and_create_gc
-        gclltype.prepare_graphs_and_create_gc = gclltype.create_gc_run_on_llinterp
-        gclltype.use_gc = DummyGC
-        cls.old = gclltype.use_gc
-
-    def teardown_class(cls):
-        gclltype.prepare_graphs_and_create_gc = cls.prep_old.im_func
-        gclltype.use_gc = cls.old
+class TestDeferredRefcountingGCRunningOnLLinterp(GCTestOnLLInterp):
+    GCClass = DeferredRefcountingGC
 

Modified: pypy/dist/pypy/rpython/memory/test/test_transformed_gc.py
==============================================================================
--- pypy/dist/pypy/rpython/memory/test/test_transformed_gc.py	(original)
+++ pypy/dist/pypy/rpython/memory/test/test_transformed_gc.py	Thu May 18 02:12:13 2006
@@ -298,3 +298,13 @@
     class gcpolicy(gc.StacklessFrameworkGcPolicy):
         class transformerclass(gctransform.StacklessFrameworkGCTransformer):
             GC_PARAMS = {'start_heap_size': 4096 }
+
+class TestSemiSpaceGC(TestMarkSweepGC):
+
+    def setup_class(cls):
+        py.test.skip("in-progress")
+
+    class gcpolicy(gc.StacklessFrameworkGcPolicy):
+        class transformerclass(gctransform.FrameworkGCTransformer):
+            from pypy.rpython.memory.gc import SemiSpaceGC as GCClass
+            GC_PARAMS = {'space_size': 4096 }


From pedronis at codespeak.net  Thu May 18 04:04:33 2006
From: pedronis at codespeak.net (pedronis at codespeak.net)
Date: Thu, 18 May 2006 04:04:33 +0200 (CEST)
Subject: [pypy-svn] r27381 - in pypy/dist/pypy/rpython: lltypesystem
	ootypesystem
Message-ID: <20060518020433.4728C10063@code0.codespeak.net>

Author: pedronis
Date: Thu May 18 04:04:29 2006
New Revision: 27381

Modified:
   pypy/dist/pypy/rpython/lltypesystem/exceptiondata.py
   pypy/dist/pypy/rpython/ootypesystem/exceptiondata.py
Log:
streamline: use annotate_helper_fn helper


Modified: pypy/dist/pypy/rpython/lltypesystem/exceptiondata.py
==============================================================================
--- pypy/dist/pypy/rpython/lltypesystem/exceptiondata.py	(original)
+++ pypy/dist/pypy/rpython/lltypesystem/exceptiondata.py	Thu May 18 04:04:29 2006
@@ -1,6 +1,5 @@
 from pypy.annotation import model as annmodel
 from pypy.rpython.lltypesystem import rclass
-from pypy.rpython.annlowlevel import annotate_lowlevel_helper
 from pypy.rpython.lltypesystem.lltype import \
      Array, malloc, Ptr, PyObject, pyobjectptr, \
      FuncType, functionptr, Signed
@@ -21,26 +20,23 @@
     def make_exception_matcher(self, rtyper):
         # ll_exception_matcher(real_exception_vtable, match_exception_vtable)
         s_typeptr = annmodel.SomePtr(self.lltype_of_exception_type)
-        helper_graph = annotate_lowlevel_helper(
-            rtyper.annotator, rclass.ll_issubclass, [s_typeptr, s_typeptr])
-        return rtyper.getcallable(helper_graph)
+        helper_fn = rtyper.annotate_helper_fn(rclass.ll_issubclass, [s_typeptr, s_typeptr])
+        return helper_fn
 
 
     def make_raise_OSError(self, rtyper):
         # ll_raise_OSError(errno)
         def ll_raise_OSError(errno):
             raise OSError(errno, None)
-        helper_graph = annotate_lowlevel_helper(
-            rtyper.annotator, ll_raise_OSError, [annmodel.SomeInteger()])
-        return rtyper.getcallable(helper_graph)
+        helper_fn = rtyper.annotate_helper_fn(ll_raise_OSError, [annmodel.SomeInteger()])
+        return helper_fn
 
 
     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)
-        helper_graph = annotate_lowlevel_helper(
-            rtyper.annotator, rclass.ll_type, [s_excinst])
-        return rtyper.getcallable(helper_graph)
+        helper_fn = rtyper.annotate_helper_fn(rclass.ll_type, [s_excinst])
+        return helper_fn
 
 
     def make_pyexcclass2exc(self, rtyper):
@@ -118,6 +114,5 @@
             return default_excinst
 
         s_pyobj = annmodel.SomePtr(Ptr(PyObject))
-        helper_graph = annotate_lowlevel_helper(
-            rtyper.annotator, ll_pyexcclass2exc, [s_pyobj])
-        return rtyper.getcallable(helper_graph)
+        helper_fn = rtyper.annotate_helper_fn(ll_pyexcclass2exc, [s_pyobj])
+        return helper_fn

Modified: pypy/dist/pypy/rpython/ootypesystem/exceptiondata.py
==============================================================================
--- pypy/dist/pypy/rpython/ootypesystem/exceptiondata.py	(original)
+++ pypy/dist/pypy/rpython/ootypesystem/exceptiondata.py	Thu May 18 04:04:29 2006
@@ -1,7 +1,6 @@
 from pypy.rpython.exceptiondata import AbstractExceptionData
 from pypy.rpython.ootypesystem import rclass
 from pypy.rpython.ootypesystem import ootype
-from pypy.rpython.annlowlevel import annotate_lowlevel_helper
 from pypy.annotation import model as annmodel
 from pypy.annotation.classdef import FORCE_ATTRIBUTES_INTO_CLASSES
 
@@ -28,16 +27,14 @@
     def make_exception_matcher(self, rtyper):
         # ll_exception_matcher(real_exception_meta, match_exception_meta)
         s_classtype = annmodel.SomeOOInstance(self.lltype_of_exception_type)
-        helper_graph = annotate_lowlevel_helper(
-            rtyper.annotator, rclass.ll_issubclass, [s_classtype, s_classtype])
-        return rtyper.getcallable(helper_graph)
-
+        helper_fn = rtyper.annotate_helper_fn(rclass.ll_issubclass, [s_classtype, s_classtype])
+        return helper_fn
+    
     def make_type_of_exc_inst(self, rtyper):
         # ll_type_of_exc_inst(exception_instance) -> exception_vtable
         s_excinst = annmodel.SomeOOInstance(self.lltype_of_exception_value)
-        helper_graph = annotate_lowlevel_helper(
-            rtyper.annotator, rclass.ll_inst_type, [s_excinst])
-        return rtyper.getcallable(helper_graph)
+        helper_fn = rtyper.annotate_helper_fn(rclass.ll_inst_type, [s_excinst])
+        return helper_fn
 
     def make_pyexcclass2exc(self, rtyper):
         # ll_pyexcclass2exc(python_exception_class) -> exception_instance


From pedronis at codespeak.net  Thu May 18 04:11:14 2006
From: pedronis at codespeak.net (pedronis at codespeak.net)
Date: Thu, 18 May 2006 04:11:14 +0200 (CEST)
Subject: [pypy-svn] r27382 - in pypy/dist/pypy/rpython: . lltypesystem
	ootypesystem
Message-ID: <20060518021114.24D241006B@code0.codespeak.net>

Author: pedronis
Date: Thu May 18 04:11:09 2006
New Revision: 27382

Modified:
   pypy/dist/pypy/rpython/annlowlevel.py
   pypy/dist/pypy/rpython/lltypesystem/ll_str.py
   pypy/dist/pypy/rpython/ootypesystem/ll_str.py
   pypy/dist/pypy/rpython/rint.py
   pypy/dist/pypy/rpython/rtyper.py
Log:
! ll_str cannot simply be removed from Reprs.

it is used by % formatting and other ll_strs. In those
cases thee one for floats was now used causing various tests
to break (even under translator/c in quite unexpected ways).

attach the rtyper to the low-level annotation policy during rtyping
and introduce a specialisation that can pick out of modules under xxtypesystem
a function based on which type system is in use:

specialize:ts('.')

use it for IntegerRepr.ll_str .



Modified: pypy/dist/pypy/rpython/annlowlevel.py
==============================================================================
--- pypy/dist/pypy/rpython/annlowlevel.py	(original)
+++ pypy/dist/pypy/rpython/annlowlevel.py	Thu May 18 04:11:09 2006
@@ -47,6 +47,9 @@
     # if this exists and is boolean, then it always wins:
     override_do_imports_immediately = True
 
+    def __init__(pol, rtyper=None):
+        pol.rtyper = rtyper
+
     def default_specialize(pol, funcdesc, args_s):
         key = []
         new_args_s = []
@@ -86,9 +89,20 @@
         exttypeinfo = extfunctable.typetable[s_value.knowntype]
         return annmodel.SomePtr(lltype.Ptr(exttypeinfo.get_lltype()))
 
-
-def annotate_lowlevel_helper(annotator, ll_function, args_s):
-    return annotator.annotate_helper(ll_function, args_s, policy= LowLevelAnnotatorPolicy())
+    def specialize__ts(pol, funcdesc, args_s, ref):
+        ts = pol.rtyper.type_system
+        ref = ref.split('.')
+        x = ts
+        for part in ref:
+            x = getattr(x, part)
+        bk = pol.rtyper.annotator.bookkeeper
+        funcdesc2 = bk.getdesc(x)
+        return pol.default_specialize(funcdesc2, args_s)
+
+def annotate_lowlevel_helper(annotator, ll_function, args_s, policy=None):
+    if policy is None:
+        policy= LowLevelAnnotatorPolicy()
+    return annotator.annotate_helper(ll_function, args_s, policy)
 
 # ___________________________________________________________________
 # Mix-level helpers: combining RPython and ll-level

Modified: pypy/dist/pypy/rpython/lltypesystem/ll_str.py
==============================================================================
--- pypy/dist/pypy/rpython/lltypesystem/ll_str.py	(original)
+++ pypy/dist/pypy/rpython/lltypesystem/ll_str.py	Thu May 18 04:11:09 2006
@@ -3,6 +3,9 @@
 
 CHAR_ARRAY = GcArray(Char)
 
+def ll_int_str(repr, i):
+    return ll_int2dec(i)
+
 def ll_int2dec(i):
     from pypy.rpython.lltypesystem.rstr import STR
     temp = malloc(CHAR_ARRAY, 20)

Modified: pypy/dist/pypy/rpython/ootypesystem/ll_str.py
==============================================================================
--- pypy/dist/pypy/rpython/ootypesystem/ll_str.py	(original)
+++ pypy/dist/pypy/rpython/ootypesystem/ll_str.py	Thu May 18 04:11:09 2006
@@ -3,6 +3,9 @@
 def const(c):
     return c
 
+def ll_int_str(repr, i):
+    return ll_int2dec(i)
+
 def ll_int2dec(i):
     return ootype.oostring(i, const(10))
 

Modified: pypy/dist/pypy/rpython/rint.py
==============================================================================
--- pypy/dist/pypy/rpython/rint.py	(original)
+++ pypy/dist/pypy/rpython/rint.py	Thu May 18 04:11:09 2006
@@ -298,9 +298,11 @@
         vlist = hop.inputargs(Float)
         return vlist[0]
 
-    def rtype_str(self, hop):
-        fn = hop.rtyper.type_system.ll_str.ll_int2dec
-        return hop.gendirectcall(fn, hop.args_v[0])
+    # version picked by specialisation based on which
+    # type system rtyping is using, from .ll_str module
+    def ll_str(self, i):
+        pass
+    ll_str._annspecialcase_ = "specialize:ts('ll_str.ll_int_str')"
 
     def rtype_hex(self, hop):
         self = self.as_int

Modified: pypy/dist/pypy/rpython/rtyper.py
==============================================================================
--- pypy/dist/pypy/rpython/rtyper.py	(original)
+++ pypy/dist/pypy/rpython/rtyper.py	Thu May 18 04:11:09 2006
@@ -28,7 +28,7 @@
 from pypy.rpython.error import TyperError
 from pypy.rpython.rmodel import Repr, inputconst, BrokenReprTyperError
 from pypy.rpython.rmodel import warning, HalfConcreteWrapper
-from pypy.rpython.annlowlevel import annotate_lowlevel_helper
+from pypy.rpython.annlowlevel import annotate_lowlevel_helper, LowLevelAnnotatorPolicy
 from pypy.rpython.rmodel import log
 from pypy.rpython.typesystem import LowLevelTypeSystem,\
                                     ObjectOrientedTypeSystem
@@ -39,6 +39,8 @@
     def __init__(self, annotator, type_system="lltype"):
         self.annotator = annotator
 
+        self.lowlevel_ann_policy = LowLevelAnnotatorPolicy(self)
+
         if isinstance(type_system, str):
             if type_system == "lltype":
                 self.type_system = LowLevelTypeSystem.instance
@@ -588,7 +590,8 @@
             args_s.insert(0, bk.immutablevalue(ll_function.im_self))
             ll_function = ll_function.im_func
         helper_graph = annotate_lowlevel_helper(self.annotator,
-                                                ll_function, args_s)
+                                                ll_function, args_s,
+                                                policy=self.lowlevel_ann_policy)
         return helper_graph
 
     def annotate_helper_fn(self, ll_function, argtypes):
@@ -604,8 +607,7 @@
         if ARG_GCSTRUCT is None:
             ARG_GCSTRUCT = GCSTRUCT
         args_s = [annmodel.SomePtr(Ptr(ARG_GCSTRUCT))]
-        graph = annotate_lowlevel_helper(self.annotator,
-                                         func, args_s)
+        graph = self.annotate_helper(func, args_s)
         s = self.annotator.binding(graph.getreturnvar())
         if (not isinstance(s, annmodel.SomePtr) or
             s.ll_ptrtype != Ptr(RuntimeTypeInfo)):
@@ -843,7 +845,8 @@
             newargs_v.insert(0, inputconst(Void, ll_function.im_self))
             ll_function = ll_function.im_func
 
-        graph = annotate_lowlevel_helper(rtyper.annotator, ll_function, args_s)
+        graph = annotate_lowlevel_helper(rtyper.annotator, ll_function, args_s,
+                                         rtyper.lowlevel_ann_policy)
         self.record_extra_call(graph)
 
         # build the 'direct_call' operation


From ericvrp at codespeak.net  Thu May 18 10:26:01 2006
From: ericvrp at codespeak.net (ericvrp at codespeak.net)
Date: Thu, 18 May 2006 10:26:01 +0200 (CEST)
Subject: [pypy-svn] r27386 - pypy/dist/pypy/jit/codegen/llvm
Message-ID: <20060518082601.ACAE210063@code0.codespeak.net>

Author: ericvrp
Date: Thu May 18 10:26:00 2006
New Revision: 27386

Modified:
   pypy/dist/pypy/jit/codegen/llvm/jitcode.py
Log:
Fix for upcoming switchback to using 'internal' linkage method in genllvm.


Modified: pypy/dist/pypy/jit/codegen/llvm/jitcode.py
==============================================================================
--- pypy/dist/pypy/jit/codegen/llvm/jitcode.py	(original)
+++ pypy/dist/pypy/jit/codegen/llvm/jitcode.py	Thu May 18 10:26:00 2006
@@ -41,6 +41,7 @@
         self.db.exceptionpolicy = ExceptionPolicy.new(self.db, 'explicit')
         self.code = StringIO()
         self.codewriter = JITCodeWriter(self.code, self.db)
+        self.codewriter.linkage = '' #XXX default linkage is internal which does not work here
         self.opwriter = JITOpWriter(self.db, self.codewriter)
         self.graph_ref = {} #name by which LLVM knowns a graph
 


From antocuni at codespeak.net  Thu May 18 10:32:32 2006
From: antocuni at codespeak.net (antocuni at codespeak.net)
Date: Thu, 18 May 2006 10:32:32 +0200 (CEST)
Subject: [pypy-svn] r27387 - in pypy/dist/pypy/rpython: lltypesystem test
Message-ID: <20060518083232.E59BB10063@code0.codespeak.net>

Author: antocuni
Date: Thu May 18 10:32:26 2006
New Revision: 27387

Modified:
   pypy/dist/pypy/rpython/lltypesystem/rstr.py
   pypy/dist/pypy/rpython/test/test_rstr.py
Log:
Fixed some bad references to ll_int2hex & co.



Modified: pypy/dist/pypy/rpython/lltypesystem/rstr.py
==============================================================================
--- pypy/dist/pypy/rpython/lltypesystem/rstr.py	(original)
+++ pypy/dist/pypy/rpython/lltypesystem/rstr.py	Thu May 18 10:32:26 2006
@@ -7,7 +7,7 @@
 from pypy.rpython.rstr import AbstractStringRepr,AbstractCharRepr,\
      AbstractUniCharRepr, AbstractStringIteratorRepr,\
      AbstractLLHelpers
-from pypy.rpython import rint
+from pypy.rpython.lltypesystem import ll_str
 from pypy.rpython.lltypesystem.lltype import \
      GcStruct, Signed, Array, Char, UniChar, Ptr, malloc, \
      Bool, Void, GcArray, nullptr, pyobjectptr
@@ -624,17 +624,18 @@
                     vchunk = hop.gendirectcall(r_arg.ll_str, vitem)
                 elif code == 'd':
                     assert isinstance(r_arg, IntegerRepr)
-                    vchunk = hop.gendirectcall(r_arg.ll_str, vitem)
+                    #vchunk = hop.gendirectcall(r_arg.ll_str, vitem)
+                    vchunk = hop.gendirectcall(ll_str.ll_int2dec, vitem)
                 elif code == 'f':
                     #assert isinstance(r_arg, FloatRepr)
                     vchunk = hop.gendirectcall(r_arg.ll_str, vitem)
                 elif code == 'x':
                     assert isinstance(r_arg, IntegerRepr)
-                    vchunk = hop.gendirectcall(rint.ll_int2hex, vitem,
+                    vchunk = hop.gendirectcall(ll_str.ll_int2hex, vitem,
                                                inputconst(Bool, False))
                 elif code == 'o':
                     assert isinstance(r_arg, IntegerRepr)
-                    vchunk = hop.gendirectcall(rint.ll_int2oct, vitem,
+                    vchunk = hop.gendirectcall(ll_str.ll_int2oct, vitem,
                                                inputconst(Bool, False))
                 else:
                     raise TyperError, "%%%s is not RPython" % (code, )
@@ -701,5 +702,3 @@
 list_str_open_bracket = string_repr.convert_const("[")
 list_str_close_bracket = string_repr.convert_const("]")
 list_str_sep = string_repr.convert_const(", ")
-
-import ll_str # side-effects due to __extend__

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 May 18 10:32:26 2006
@@ -356,6 +356,8 @@
 
 
     def test_strformat(self):
+        self._skip_oo('string formatting')
+        
         def percentS(s):
             return "before %s after" % (s,)
 


From ericvrp at codespeak.net  Thu May 18 12:35:06 2006
From: ericvrp at codespeak.net (ericvrp at codespeak.net)
Date: Thu, 18 May 2006 12:35:06 +0200 (CEST)
Subject: [pypy-svn] r27400 - in pypy/dist/pypy/translator/llvm: . externs
	module test
Message-ID: <20060518103506.CCE241006B@code0.codespeak.net>

Author: ericvrp
Date: Thu May 18 12:35:05 2006
New Revision: 27400

Removed:
   pypy/dist/pypy/translator/llvm/externs/
Modified:
   pypy/dist/pypy/translator/llvm/buildllvm.py
   pypy/dist/pypy/translator/llvm/codewriter.py
   pypy/dist/pypy/translator/llvm/externs2ll.py
   pypy/dist/pypy/translator/llvm/gc.py
   pypy/dist/pypy/translator/llvm/module/boehm.h
   pypy/dist/pypy/translator/llvm/module/protos.h
   pypy/dist/pypy/translator/llvm/test/test_extfunc.py
Log:
* Fixed and enabled genllvm's performance that used a ringbuffer for some
  exception mallocs. For this I moved some code back from python to C
  because I had to call the regular pypy_malloc (which is in C) when the
  size of the (to be allocated) data would not fit into a ringbuffer entry.
* Refactored codewriter a little to allow the code in jit/codegen/llvm to
  use it without the internal linkage type


Modified: pypy/dist/pypy/translator/llvm/buildllvm.py
==============================================================================
--- pypy/dist/pypy/translator/llvm/buildllvm.py	(original)
+++ pypy/dist/pypy/translator/llvm/buildllvm.py	Thu May 18 12:35:05 2006
@@ -35,6 +35,7 @@
         opts += "-globalopt -constmerge -ipsccp -deadargelim -inline " \
                 "-instcombine -scalarrepl -globalsmodref-aa -licm -load-vn " \
                 "-gcse -instcombine -simplifycfg -globaldce "
+        #opts += "-inline-threshold=200 "   #default: 200
     return opts
 
 def compile_module(module, source_files, object_files, library_files):

Modified: pypy/dist/pypy/translator/llvm/codewriter.py
==============================================================================
--- pypy/dist/pypy/translator/llvm/codewriter.py	(original)
+++ pypy/dist/pypy/translator/llvm/codewriter.py	Thu May 18 12:35:05 2006
@@ -4,12 +4,16 @@
 
 DEFAULT_TAIL     = ''       #/tail
 DEFAULT_CCONV    = 'fastcc'    #ccc/fastcc
-DEFAULT_LINKAGE  = ''       #/internal (disabled for now because of the JIT)
+DEFAULT_LINKAGE  = 'internal '       #/internal (disabled for now because of the JIT)
 
 class CodeWriter(object): 
-    def __init__(self, file, db): 
+    def __init__(self, file, db, tail=DEFAULT_TAIL, cconv=DEFAULT_CCONV,
+                                 linkage=DEFAULT_LINKAGE): 
         self.file = file
         self.word_repr = db.get_machine_word()
+        self.tail = tail
+        self.cconv = cconv
+        self.linkage = linkage
 
     def close(self): 
         self.file.close()
@@ -60,7 +64,9 @@
         self.newline()
         self._append("    %s:" % name)
 
-    def globalinstance(self, name, typeandata, linkage=DEFAULT_LINKAGE):
+    def globalinstance(self, name, typeandata, linkage=None):
+        if linkage is None:
+            linkage = self.linkage
         self._append("%s = %sglobal %s" % (name, linkage, typeandata))
 
     def typedef(self, name, type_):
@@ -76,7 +82,9 @@
         self.typedef(name, "%s (%s)" % (rettyperepr,
                                         ", ".join(argtypereprs)))
 
-    def declare(self, decl, cconv=DEFAULT_CCONV):
+    def declare(self, decl, cconv=None):
+        if cconv is None:
+            cconv = self.cconv
         self._append("declare %s %s" %(cconv, decl,))
 
     def startimpl(self):
@@ -100,7 +108,11 @@
         self._indent("switch %s %s, label %%%s [%s ]"
                      % (intty, cond, defaultdest, labels))
 
-    def openfunc(self, decl, cconv=DEFAULT_CCONV, linkage=DEFAULT_LINKAGE): 
+    def openfunc(self, decl, cconv=None, linkage=None): 
+        if cconv is None:
+            cconv = self.cconv
+        if linkage is None:
+            linkage = self.linkage
         self.newline()
         self._append("%s%s %s {" % (linkage, cconv, decl,))
 
@@ -163,8 +175,12 @@
         self._indent("unwind")
 
     def call(self, targetvar, returntype, functionref, argtypes, argrefs,
-             tail=DEFAULT_TAIL, cconv=DEFAULT_CCONV):
-
+             tail=None, cconv=None):
+        if tail is None:
+            tail = self.tail
+        if cconv is None:
+            cconv = self.cconv
+            
         tail = self._resolvetail(tail, cconv)        
         args = ", ".join(["%s %s" % item for item in zip(argtypes, argrefs)])
 

Modified: pypy/dist/pypy/translator/llvm/externs2ll.py
==============================================================================
--- pypy/dist/pypy/translator/llvm/externs2ll.py	(original)
+++ pypy/dist/pypy/translator/llvm/externs2ll.py	Thu May 18 12:35:05 2006
@@ -135,12 +135,6 @@
         decls.append(("ll_" + func.func_name, graph))
         return graph.name
 
-    if hasattr(db.gcpolicy, 'exc_useringbuf') and db.gcpolicy.exc_useringbuf:
-        from pypy.translator.llvm.externs import ringbuffer as rb
-        g = annotatehelper(rb.ringbuffer_initialise)
-        db.gcpolicy.ringbuf_malloc_name = \
-                 annotatehelper(rb.ringbuffer_malloc, lltype.Signed)
-
     return decls
 
 def get_c_cpath():

Modified: pypy/dist/pypy/translator/llvm/gc.py
==============================================================================
--- pypy/dist/pypy/translator/llvm/gc.py	(original)
+++ pypy/dist/pypy/translator/llvm/gc.py	Thu May 18 12:35:05 2006
@@ -59,7 +59,7 @@
         return self.boehm.var_malloc(codewriter, targetvar, type_, node, len, atomic)
 
     def genextern_code(self):
-        r = ''
+        r  = ''
         r += '#define __GC_STARTUP_CODE__\n'
         r += '#define __GC_SETUP_CODE__\n'
         r += 'char* pypy_malloc(int size)        { return calloc(1, size); }\n'
@@ -69,18 +69,15 @@
 
 class BoehmGcPolicy(GcPolicy):
 
-    def __init__(self, db, exc_useringbuf=False):
+    def __init__(self, db, exc_useringbuf=True):
         self.db = db
         self.n_malloced = 0
         self.exc_useringbuf = exc_useringbuf
         
     def genextern_code(self):
-        r = '#include "boehm.h"\n'
-
-        if self.exc_useringbuf:
-            r += '#define __GC_SETUP_CODE__ ll_ringbuffer_initialise();\n'
-        else:
-            r += '#define __GC_SETUP_CODE__\n'
+        r  = ''
+        r += '#include "boehm.h"\n'
+        r += '#define __GC_SETUP_CODE__\n'
         return r
     
     def gc_libraries(self):
@@ -112,17 +109,16 @@
         word = self.db.get_machine_word()
         uword = self.db.get_machine_uword()
 
+        fnname = '%pypy_malloc' + (atomic and '_atomic' or '')
         if self.exc_useringbuf and exc_flag:
-            fnname = '%pypy_' + self.ringbuf_malloc_name
-            atomic = False
-        else:
-            fnname = '%pypy_malloc' + (atomic and '_atomic' or '')
+            fnname += '_ringbuffer'
+            atomic  = False #XXX performance hack to never clear the ringbuffer data
 
         # malloc_size is unsigned right now
         sizei = '%malloc_sizei' + self.get_count()        
         codewriter.cast(sizei, uword, size, word)
         codewriter.call(targetvar, 'sbyte*', fnname, [word], [sizei])
-        
+
         if atomic:
             codewriter.call(None, 'void', '%llvm.memset',
                             ['sbyte*', 'ubyte', uword, uword],

Modified: pypy/dist/pypy/translator/llvm/module/boehm.h
==============================================================================
--- pypy/dist/pypy/translator/llvm/module/boehm.h	(original)
+++ pypy/dist/pypy/translator/llvm/module/boehm.h	Thu May 18 12:35:05 2006
@@ -4,11 +4,14 @@
 
 #ifdef USING_THREADED_BOEHM
 
+#define GC_LINUX_THREADS 1
 #define GC_REDIRECT_TO_LOCAL 1
+#define GC_I_HIDE_POINTERS 1
 #include 
 
 #else
 
+#define GC_I_HIDE_POINTERS 1
 #include 
 
 #endif
@@ -29,3 +32,35 @@
 #define __GC_STARTUP_CODE__ \
   GC_all_interior_pointers = 0; \
   GC_init();
+
+
+// Some malloced data is expected to be short-lived (exceptions).
+// The follow is a hack to store such data in a ringbuffer.
+// This yields an extremely good speedup in certain cases but
+// fails badly (segfaults) when a reference to the data is kept
+// around and used (much) later.
+
+#define ringbufsize         1024
+#define ringbufentry_maxsize  16
+
+static  char    ringbufdata[ringbufsize + ringbufentry_maxsize];
+static  long    ringbufindex = 0;
+
+char *pypy_malloc_ringbuffer(long size) {
+    if (size <= ringbufentry_maxsize) { //test expected to be optimized away during compile time
+        ringbufindex = (ringbufindex + ringbufentry_maxsize) & (ringbufsize - 1);
+        return &ringbufdata[ringbufindex];
+    } else {
+        return GC_MALLOC(size);
+    }
+}
+
+char *pypy_malloc_atomic_ringbuffer(long size) {
+    if (size <= ringbufentry_maxsize) { //test expected to be optimized away during compile time
+        ringbufindex = (ringbufindex + ringbufentry_maxsize) & (ringbufsize - 1);
+        return &ringbufdata[ringbufindex];
+    } else {
+        return GC_MALLOC_ATOMIC(size);
+    }
+}
+

Modified: pypy/dist/pypy/translator/llvm/module/protos.h
==============================================================================
--- pypy/dist/pypy/translator/llvm/module/protos.h	(original)
+++ pypy/dist/pypy/translator/llvm/module/protos.h	Thu May 18 12:35:05 2006
@@ -17,6 +17,5 @@
   RPyListOfString *_RPyListOfString_New(long);
   void _RPyListOfString_SetItem(RPyListOfString *, int, RPyString *);
 #endif
-void ll_ringbuffer_initialise(void);
 
 // XXX end of proto hacks

Modified: pypy/dist/pypy/translator/llvm/test/test_extfunc.py
==============================================================================
--- pypy/dist/pypy/translator/llvm/test/test_extfunc.py	(original)
+++ pypy/dist/pypy/translator/llvm/test/test_extfunc.py	Thu May 18 12:35:05 2006
@@ -23,8 +23,7 @@
     assert abs(f()-fn()) < 10.0
 
 def test_external_function_ll_time_clock():
-    if sys.platform == 'darwin':
-        py.test.skip("time.clock behaving strangly on Darwin")
+    py.test.skip("XXX TODO FIXME time.clock behaving strangly")
     import time
     def fn():
         return time.clock()


From antocuni at codespeak.net  Thu May 18 12:36:57 2006
From: antocuni at codespeak.net (antocuni at codespeak.net)
Date: Thu, 18 May 2006 12:36:57 +0200 (CEST)
Subject: [pypy-svn] r27401 - in pypy/dist/pypy/rpython: ootypesystem test
Message-ID: <20060518103657.016B01006B@code0.codespeak.net>

Author: antocuni
Date: Thu May 18 12:36:51 2006
New Revision: 27401

Modified:
   pypy/dist/pypy/rpython/ootypesystem/ll_str.py
   pypy/dist/pypy/rpython/ootypesystem/ootype.py
   pypy/dist/pypy/rpython/test/test_rstr.py
Log:
Fixed a bug in ootypesystem hex() and oct() function.



Modified: pypy/dist/pypy/rpython/ootypesystem/ll_str.py
==============================================================================
--- pypy/dist/pypy/rpython/ootypesystem/ll_str.py	(original)
+++ pypy/dist/pypy/rpython/ootypesystem/ll_str.py	Thu May 18 12:36:51 2006
@@ -1,4 +1,4 @@
-from pypy.rpython.ootypesystem import ootype
+from pypy.rpython.ootypesystem.ootype import new, oostring, StringBuilder
 
 def const(c):
     return c
@@ -7,14 +7,33 @@
     return ll_int2dec(i)
 
 def ll_int2dec(i):
-    return ootype.oostring(i, const(10))
+    return oostring(i, const(10))
 
-# TODO: add support for addPrefix == False
 def ll_int2hex(i, addPrefix):
-    #assert addPrefix
-    return ootype.oostring(i, const(16))
+    if not addPrefix:
+        return oostring(i, const(16))
+
+    buf = new(StringBuilder)
+    if i<0:
+        i = -i
+        buf.ll_append_char('-')
+
+    buf.ll_append_char('0')
+    buf.ll_append_char('x')
+    buf.ll_append(oostring(i, const(16)))
+    return buf.ll_build()
 
 def ll_int2oct(i, addPrefix):
-    #assert addPrefix
-    return ootype.oostring(i, const(8))
+    if not addPrefix or i==0:
+        return oostring(i, const(8))
+
+    buf = new(StringBuilder)
+    if i<0:
+        i = -i
+        buf.ll_append_char('-')
+
+    buf.ll_append_char('0')
+    buf.ll_append(oostring(i, const(8)))
+    return buf.ll_build()
+
 

Modified: pypy/dist/pypy/rpython/ootypesystem/ootype.py
==============================================================================
--- pypy/dist/pypy/rpython/ootypesystem/ootype.py	(original)
+++ pypy/dist/pypy/rpython/ootypesystem/ootype.py	Thu May 18 12:36:51 2006
@@ -1169,8 +1169,8 @@
     """
     if isinstance(obj, int):
         assert base in (-1, 8, 10, 16)
-        fn = {-1: str, 8: oct, 10: str, 16: hex}[base]
-        obj = fn(obj)
+        fmt = {-1:'%d', 8:'%o', 10:'%d', 16:'%x'}[base]
+        obj = fmt % obj
     elif isinstance(obj, _view):
         obj = '<%s object>' % obj._inst._TYPE._name
     return make_string(str(obj))

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 May 18 12:36:51 2006
@@ -356,8 +356,6 @@
 
 
     def test_strformat(self):
-        self._skip_oo('string formatting')
-        
         def percentS(s):
             return "before %s after" % (s,)
 


From cfbolz at codespeak.net  Thu May 18 13:08:41 2006
From: cfbolz at codespeak.net (cfbolz at codespeak.net)
Date: Thu, 18 May 2006 13:08:41 +0200 (CEST)
Subject: [pypy-svn] r27405 - pypy/dist/pypy/rpython/test
Message-ID: <20060518110841.B64211006B@code0.codespeak.net>

Author: cfbolz
Date: Thu May 18 13:08:40 2006
New Revision: 27405

Modified:
   pypy/dist/pypy/rpython/test/test_objectmodel.py
Log:
this function was renamed, fix test


Modified: pypy/dist/pypy/rpython/test/test_objectmodel.py
==============================================================================
--- pypy/dist/pypy/rpython/test/test_objectmodel.py	(original)
+++ pypy/dist/pypy/rpython/test/test_objectmodel.py	Thu May 18 13:08:40 2006
@@ -75,9 +75,9 @@
     class B(object):
         pass
     a = A()
-    addr = cast_object_to_address(a)
-    py.test.raises(AssertionError, "cast_address_to_object(addr, B)")
-    assert a is cast_address_to_object(addr, A)
+    addr = cast_object_to_weakgcaddress(a)
+    py.test.raises(AssertionError, "cast_weakgcaddress_to_object(addr, B)")
+    assert a is cast_weakgcaddress_to_object(addr, A)
 
 def test_recursive_r_dict_repr():
     import operator


From cfbolz at codespeak.net  Thu May 18 13:22:32 2006
From: cfbolz at codespeak.net (cfbolz at codespeak.net)
Date: Thu, 18 May 2006 13:22:32 +0200 (CEST)
Subject: [pypy-svn] r27407 - pypy/dist/pypy/translator/c/test
Message-ID: <20060518112232.C31221006B@code0.codespeak.net>

Author: cfbolz
Date: Thu May 18 13:22:31 2006
New Revision: 27407

Modified:
   pypy/dist/pypy/translator/c/test/test_lladdresses.py
Log:
this test started failing because since from 27370 also raw_mallocs are counted
in the total number of mallocs. call raw_free where appropriate to stop leaking
memory and to pass the tests again.


Modified: pypy/dist/pypy/translator/c/test/test_lladdresses.py
==============================================================================
--- pypy/dist/pypy/translator/c/test/test_lladdresses.py	(original)
+++ pypy/dist/pypy/translator/c/test/test_lladdresses.py	Thu May 18 13:22:31 2006
@@ -24,7 +24,9 @@
     def f(value):
         addr = raw_malloc(16)
         addr.signed[0] = value
-        return addr.signed[0]
+        result = addr.signed[0]
+        raw_free(addr)
+        return result
     fc = compile(f, [int])
     res = fc(42)
     assert res == 42
@@ -51,7 +53,9 @@
         addr += offset
         addr.char[-offset] = char
         addr -= offset
-        return addr.char[0]
+        result = addr.char[0]
+        raw_free(addr)
+        return result
     fc = compile(f, [int, SomeChar()])
     res = fc(10, "c")
     assert res == "c"
@@ -67,6 +71,8 @@
         result = addr1.signed[0] == 12
         result = result and (addr1 + 10).signed[0] == 42
         result = result and (addr1 + 20).char[0] == "a"
+        raw_free(addr)
+        raw_free(addr1)
         return result
     fc = compile(f, [])
     res = fc()
@@ -75,7 +81,8 @@
 def test_pointer_comparison():
     def f():
         result = 0
-        for addr1 in [raw_malloc(1), NULL]:
+        addresses = [raw_malloc(1), NULL]
+        for addr1 in addresses:
             addr2 = addr1 + 1
             result = result * 2 + int(addr1 == addr2)
             result = result * 2 + int(addr1 != addr2)
@@ -83,6 +90,7 @@
             result = result * 2 + int(addr1 <= addr2)
             result = result * 2 + int(addr1 >  addr2)
             result = result * 2 + int(addr1 >= addr2)
+        raw_free(addresses[0])
         return result
     fc = compile(f, [])
     res = fc()


From ac at codespeak.net  Thu May 18 15:16:13 2006
From: ac at codespeak.net (ac at codespeak.net)
Date: Thu, 18 May 2006 15:16:13 +0200 (CEST)
Subject: [pypy-svn] r27412 - pypy/extradoc/sprintinfo/ddorf2006
Message-ID: <20060518131613.15A9D10061@code0.codespeak.net>

Author: ac
Date: Thu May 18 15:16:12 2006
New Revision: 27412

Modified:
   pypy/extradoc/sprintinfo/ddorf2006/people.txt
Log:
My and Samueles dates.

Modified: pypy/extradoc/sprintinfo/ddorf2006/people.txt
==============================================================================
--- pypy/extradoc/sprintinfo/ddorf2006/people.txt	(original)
+++ pypy/extradoc/sprintinfo/ddorf2006/people.txt	Thu May 18 15:16:12 2006
@@ -14,6 +14,8 @@
 Carl Friedrich Bolz  nope :-)       private
 Eric van Riet Paap   ?              ?
 Maciej Fijalkowski   3rd-9th        cfbolz
+Anders Chrigstroem   1st - 9th      ?
+Samuele Pedroni      1st - 9th      ?
 ==================== ============== =====================
 
 People on the following list were present at previous sprints: 
@@ -21,8 +23,6 @@
 ==================== ============== =====================
        Name          Arrive/Depart  Accomodation 
 ==================== ============== =====================
-Anders Chrigstroem   ?              ?
-Samuele Pedroni      ?              ?
 Christian Tismer     ?              ?
 Anders Lehmann       ?              ?
 Jacob Hallen         ?              ?


From antocuni at codespeak.net  Thu May 18 16:21:59 2006
From: antocuni at codespeak.net (antocuni at codespeak.net)
Date: Thu, 18 May 2006 16:21:59 +0200 (CEST)
Subject: [pypy-svn] r27415 - pypy/extradoc/sprintinfo/ddorf2006
Message-ID: <20060518142159.3FCA410072@code0.codespeak.net>

Author: antocuni
Date: Thu May 18 16:21:54 2006
New Revision: 27415

Modified:
   pypy/extradoc/sprintinfo/ddorf2006/people.txt
Log:
Added my info.



Modified: pypy/extradoc/sprintinfo/ddorf2006/people.txt
==============================================================================
--- pypy/extradoc/sprintinfo/ddorf2006/people.txt	(original)
+++ pypy/extradoc/sprintinfo/ddorf2006/people.txt	Thu May 18 16:21:54 2006
@@ -16,6 +16,7 @@
 Maciej Fijalkowski   3rd-9th        cfbolz
 Anders Chrigstroem   1st - 9th      ?
 Samuele Pedroni      1st - 9th      ?
+Antonio Cuni         1st - 9th      cfbolz
 ==================== ============== =====================
 
 People on the following list were present at previous sprints: 


From ale at codespeak.net  Fri May 19 09:16:49 2006
From: ale at codespeak.net (ale at codespeak.net)
Date: Fri, 19 May 2006 09:16:49 +0200 (CEST)
Subject: [pypy-svn] r27444 - pypy/extradoc/sprintinfo/ddorf2006
Message-ID: <20060519071649.AFFC61006B@code0.codespeak.net>

Author: ale
Date: Fri May 19 09:16:48 2006
New Revision: 27444

Modified:
   pypy/extradoc/sprintinfo/ddorf2006/people.txt
Log:
My preliminary info

Modified: pypy/extradoc/sprintinfo/ddorf2006/people.txt
==============================================================================
--- pypy/extradoc/sprintinfo/ddorf2006/people.txt	(original)
+++ pypy/extradoc/sprintinfo/ddorf2006/people.txt	Fri May 19 09:16:48 2006
@@ -17,6 +17,7 @@
 Anders Chrigstroem   1st - 9th      ?
 Samuele Pedroni      1st - 9th      ?
 Antonio Cuni         1st - 9th      cfbolz
+Anders Lehmann       2nd - 9th      ?
 ==================== ============== =====================
 
 People on the following list were present at previous sprints: 
@@ -25,7 +26,6 @@
        Name          Arrive/Depart  Accomodation 
 ==================== ============== =====================
 Christian Tismer     ?              ?
-Anders Lehmann       ?              ?
 Jacob Hallen         ?              ?
 Niklaus Haldimann    ?              ?
 Aurelien Campeas     ?              ?


From ericvrp at codespeak.net  Fri May 19 09:47:37 2006
From: ericvrp at codespeak.net (ericvrp at codespeak.net)
Date: Fri, 19 May 2006 09:47:37 +0200 (CEST)
Subject: [pypy-svn] r27445 - pypy/dist/pypy/doc
Message-ID: <20060519074737.E087E1006B@code0.codespeak.net>

Author: ericvrp
Date: Fri May 19 09:47:36 2006
New Revision: 27445

Modified:
   pypy/dist/pypy/doc/news.txt
Log:
The Tokyo sprint is over and Dusseldorf is upon us.


Modified: pypy/dist/pypy/doc/news.txt
==============================================================================
--- pypy/dist/pypy/doc/news.txt	(original)
+++ pypy/dist/pypy/doc/news.txt	Fri May 19 09:47:36 2006
@@ -7,18 +7,27 @@
 .. _Python: http://www.python.org/doc/current/ref/ref.html
 .. _`more...`: http://codespeak.net/pypy/dist/pypy/doc/architecture.html#mission-statement 
 
-Next PyPy sprint in Tokyo 23rd - 29th April 2006
+Duesseldorf PyPy sprint 2-9 June 2006
 ==================================================================
 
-The next sprint will be Akihabara, Tokyo, Japan. Our hosts are
-FSIJ (Free Software Initiative of Japan) and out aim for the sprint
-will be to promote Python and introduce people to PyPy.
+The next PyPy sprint will be held in the Computer Science department of
+Heinrich-Heine Universitaet Duesseldorf from the *2nd to the 9th of June*.
+Main focus of the sprint will be on the goals of the upcoming June 0.9
+release.
 
 Read more in `the sprint announcement`_, see who is  planning to attend
 on the `people page`_.
 
-.. _`the sprint announcement`: http://codespeak.net/pypy/extradoc/sprintinfo/tokyo/sprint-announcement.html
-.. _`people page`: http://codespeak.net/pypy/extradoc/sprintinfo/tokyo/people.html
+.. _`the sprint announcement`: http://codespeak.net/pypy/extradoc/sprintinfo/ddorf2006/sprint-announcement.html
+.. _`people page`: http://codespeak.net/pypy/extradoc/sprintinfo/ddorf2006/people.html
+
+PyPy sprint in Tokyo 23rd - 29th April 2006
+==================================================================
+
+This sprint was in Akihabara, Tokyo, Japan, our hosts was
+FSIJ (Free Software Initiative of Japan) and we aimed for the sprint
+to promote Python and introduce people to PyPy. Good progress was also made
+on PyPy's ootypesystem for the more high level backends.
 
 PyPy at XPDay France 2006 in Paris March 23rd - March 24th 2006
 ==================================================================


From ericvrp at codespeak.net  Fri May 19 09:58:13 2006
From: ericvrp at codespeak.net (ericvrp at codespeak.net)
Date: Fri, 19 May 2006 09:58:13 +0200 (CEST)
Subject: [pypy-svn] r27446 - pypy/dist/pypy/doc
Message-ID: <20060519075813.E399910071@code0.codespeak.net>

Author: ericvrp
Date: Fri May 19 09:58:13 2006
New Revision: 27446

Modified:
   pypy/dist/pypy/doc/news.txt
Log:
sprint announcement file was named differently this time.
(I should have tested with py.test -R)


Modified: pypy/dist/pypy/doc/news.txt
==============================================================================
--- pypy/dist/pypy/doc/news.txt	(original)
+++ pypy/dist/pypy/doc/news.txt	Fri May 19 09:58:13 2006
@@ -18,7 +18,7 @@
 Read more in `the sprint announcement`_, see who is  planning to attend
 on the `people page`_.
 
-.. _`the sprint announcement`: http://codespeak.net/pypy/extradoc/sprintinfo/ddorf2006/sprint-announcement.html
+.. _`the sprint announcement`: http://codespeak.net/pypy/extradoc/sprintinfo/ddorf2006/announce.html
 .. _`people page`: http://codespeak.net/pypy/extradoc/sprintinfo/ddorf2006/people.html
 
 PyPy sprint in Tokyo 23rd - 29th April 2006


From arigo at codespeak.net  Fri May 19 11:38:16 2006
From: arigo at codespeak.net (arigo at codespeak.net)
Date: Fri, 19 May 2006 11:38:16 +0200 (CEST)
Subject: [pypy-svn] r27450 - pypy/dist/pypy/rpython/lltypesystem
Message-ID: <20060519093816.9AAB710061@code0.codespeak.net>

Author: arigo
Date: Fri May 19 11:38:15 2006
New Revision: 27450

Modified:
   pypy/dist/pypy/rpython/lltypesystem/lltype.py
Log:
Python 2.5 compatibility.


Modified: pypy/dist/pypy/rpython/lltypesystem/lltype.py
==============================================================================
--- pypy/dist/pypy/rpython/lltypesystem/lltype.py	(original)
+++ pypy/dist/pypy/rpython/lltypesystem/lltype.py	Fri May 19 11:38:15 2006
@@ -1035,7 +1035,7 @@
         if isinstance(obj, int):
             return obj     # special case for cast_int_to_ptr() results
         obj = top_container(obj)
-        result = id(obj)
+        result = intmask(id(obj))
         # assume that id() returns an addressish value which is
         # not zero and aligned to at least a multiple of 4
         assert result != 0 and (result & 3) == 0


From antocuni at codespeak.net  Fri May 19 12:16:08 2006
From: antocuni at codespeak.net (antocuni at codespeak.net)
Date: Fri, 19 May 2006 12:16:08 +0200 (CEST)
Subject: [pypy-svn] r27460 - in pypy/dist/pypy/rpython/ootypesystem: . test
Message-ID: <20060519101608.3CFA21006E@code0.codespeak.net>

Author: antocuni
Date: Fri May 19 12:16:06 2006
New Revision: 27460

Added:
   pypy/dist/pypy/rpython/ootypesystem/ooregistry.py   (contents, props changed)
   pypy/dist/pypy/rpython/ootypesystem/test/test_ooregistry.py   (contents, props changed)
Modified:
   pypy/dist/pypy/rpython/ootypesystem/ootype.py
Log:
Played a bit with extregistry.



Added: pypy/dist/pypy/rpython/ootypesystem/ooregistry.py
==============================================================================
--- (empty file)
+++ pypy/dist/pypy/rpython/ootypesystem/ooregistry.py	Fri May 19 12:16:06 2006
@@ -0,0 +1,22 @@
+from pypy.rpython.extregistry import ExtRegistryEntry
+from pypy.annotation import model as annmodel
+from pypy.rpython.ootypesystem import ootype
+
+class OOStringEntry(ExtRegistryEntry):
+    _about_ = ootype.oostring2
+
+    def compute_result_annotation(self, obj_s, base_s):
+        assert isinstance(obj_s, (annmodel.SomeInteger,
+                                annmodel.SomeChar,
+                                annmodel.SomeOOInstance))
+        assert isinstance(base_s, annmodel.SomeInteger)
+        return annmodel.SomeOOInstance(ootype.String)
+
+    def specialize_call(self, hop):
+        assert isinstance(hop.args_s[0],(annmodel.SomeInteger,
+                                         annmodel.SomeChar,
+                                         annmodel.SomeString,
+                                         annmodel.SomeOOInstance))
+        assert isinstance(hop.args_s[1], annmodel.SomeInteger)
+        return hop.genop('oostring', hop.args_v, resulttype = ootype.String)
+        

Modified: pypy/dist/pypy/rpython/ootypesystem/ootype.py
==============================================================================
--- pypy/dist/pypy/rpython/ootypesystem/ootype.py	(original)
+++ pypy/dist/pypy/rpython/ootypesystem/ootype.py	Fri May 19 12:16:06 2006
@@ -1175,6 +1175,18 @@
         obj = '<%s object>' % obj._inst._TYPE._name
     return make_string(str(obj))
 
+def oostring2(obj, base):
+    """
+    Temp function for playing with extregistry.
+    """
+    if isinstance(obj, int):
+        assert base in (-1, 8, 10, 16)
+        fmt = {-1:'%d', 8:'%o', 10:'%d', 16:'%x'}[base]
+        obj = fmt % obj
+    elif isinstance(obj, _view):
+        obj = '<%s object>' % obj._inst._TYPE._name
+    return make_string(str(obj))
+
 def ooparse_int(s, base):
     return int(s._str, base)
 

Added: pypy/dist/pypy/rpython/ootypesystem/test/test_ooregistry.py
==============================================================================
--- (empty file)
+++ pypy/dist/pypy/rpython/ootypesystem/test/test_ooregistry.py	Fri May 19 12:16:06 2006
@@ -0,0 +1,32 @@
+from pypy.annotation.annrpython import RPythonAnnotator
+from pypy.annotation import model as annmodel
+from pypy.rpython.ootypesystem import ooregistry # side effects
+from pypy.rpython.ootypesystem import ootype
+from pypy.rpython.test.test_llinterp import interpret
+
+def test_oostring2_annotation():
+    def oof():
+        return ootype.oostring2
+
+    a = RPythonAnnotator()
+    s = a.build_types(oof, [])
+    assert isinstance(s, annmodel.SomeBuiltin)
+
+def test_oostring2_result_annotation():
+    def oof():
+        return ootype.oostring2(42, -1)
+
+    a = RPythonAnnotator()
+    s = a.build_types(oof, [])
+    assert isinstance(s, annmodel.SomeOOInstance) and s.ootype is ootype.String
+
+def test_oostring2_call():
+    def const(c):
+        return c
+    
+    def oof(ch):
+        return ootype.oostring2(ch, const(-1))
+
+    ch = 'a'
+    res = interpret(oof, [ch], type_system='ootype')
+    assert res._str == 'a'


From ericvrp at codespeak.net  Fri May 19 12:16:59 2006
From: ericvrp at codespeak.net (ericvrp at codespeak.net)
Date: Fri, 19 May 2006 12:16:59 +0200 (CEST)
Subject: [pypy-svn] r27461 - in pypy/dist/pypy/doc: . weekly
Message-ID: <20060519101659.E05801006E@code0.codespeak.net>

Author: ericvrp
Date: Fri May 19 12:16:58 2006
New Revision: 27461

Modified:
   pypy/dist/pypy/doc/extradoc.txt
   pypy/dist/pypy/doc/getting-started.txt
   pypy/dist/pypy/doc/weekly/summary-2006-03-15.txt
Log:
Fixed some external links in our documentation.


Modified: pypy/dist/pypy/doc/extradoc.txt
==============================================================================
--- pypy/dist/pypy/doc/extradoc.txt	(original)
+++ pypy/dist/pypy/doc/extradoc.txt	Fri May 19 12:16:58 2006
@@ -51,7 +51,7 @@
   a good introduction to the underlying models of Microsoft's Common 
   Language Runtime, the Intermediate Language, JIT and GC issues. 
   
-* spyweb_ translates Python programs to Scheme. 
+* spyweb translates Python programs to Scheme. (site unavailable)
 
 * Jython_ is a Python implementation in Java.
 
@@ -72,7 +72,6 @@
 .. _testdesign: http://codespeak.net/pypy/dist/pypy/doc/coding-guide.html#test-design
 .. _feasible: http://codespeak.net/pipermail/pypy-dev/2004q2/001289.html
 .. _rock: http://codespeak.net/pipermail/pypy-dev/2004q1/001255.html
-.. _spyweb: http://spyweb.hopto.org/
 .. _`GNU lightning`: http://www.gnu.org/software/lightning/lightning.html
 .. _LLVM: http://llvm.org/
 .. _IronPython: http://www.python.org/pycon/dc2004/papers/9/

Modified: pypy/dist/pypy/doc/getting-started.txt
==============================================================================
--- pypy/dist/pypy/doc/getting-started.txt	(original)
+++ pypy/dist/pypy/doc/getting-started.txt	Fri May 19 12:16:58 2006
@@ -607,7 +607,7 @@
 graphviz and pygame are both neccessary if you
 want to look at generated flowgraphs: 
 
-	graphviz: http://www.research.att.com/sw/tools/graphviz/download.html 
+	graphviz: http://www.graphviz.org/Download.php 
 
 	pygame: http://www.pygame.org/download.shtml
 
@@ -661,7 +661,7 @@
 .. _`Spidermonkey`: http://www.mozilla.org/js/spidermonkey/
 .. _`Google summer of code`: http://code.google.com/soc
 
-.. _Dot Graphviz:           http://www.research.att.com/sw/tools/graphviz/
+.. _Dot Graphviz:           http://www.graphviz.org/
 .. _Pygame:                 http://www.pygame.org/
 .. _pyopcode.py:            http://codespeak.net/svn/pypy/dist/pypy/interpreter/pyopcode.py
 .. _eval.py:                http://codespeak.net/svn/pypy/dist/pypy/interpreter/eval.py

Modified: pypy/dist/pypy/doc/weekly/summary-2006-03-15.txt
==============================================================================
--- pypy/dist/pypy/doc/weekly/summary-2006-03-15.txt	(original)
+++ pypy/dist/pypy/doc/weekly/summary-2006-03-15.txt	Fri May 19 12:16:58 2006
@@ -19,11 +19,9 @@
 talks, talked to a great many interested people and held a successful
 sprint, giving several newcomers their first taste of hacking on PyPy.
 
-You can read more about this in the `conference report`_ and `sprint
-report`_.
+You can read more about this in the `sprint report`_.
 
-.. _`conference report`: http://write.me/
-.. _`sprint report`: http://write.me/
+.. _`sprint report`: http://codespeak.net/pypy/extradoc/sprintinfo/pycon06/sprint-report.txt
 
 The Logic Sprint
 ================


From arigo at codespeak.net  Fri May 19 13:28:12 2006
From: arigo at codespeak.net (arigo at codespeak.net)
Date: Fri, 19 May 2006 13:28:12 +0200 (CEST)
Subject: [pypy-svn] r27466 - in pypy/dist/pypy/rpython: lltypesystem
	lltypesystem/test memory memory/test
Message-ID: <20060519112812.499D410063@code0.codespeak.net>

Author: arigo
Date: Fri May 19 13:28:09 2006
New Revision: 27466

Modified:
   pypy/dist/pypy/rpython/lltypesystem/lloperation.py
   pypy/dist/pypy/rpython/lltypesystem/test/test_lloperation.py
   pypy/dist/pypy/rpython/memory/gc.py
   pypy/dist/pypy/rpython/memory/gctransform.py
   pypy/dist/pypy/rpython/memory/test/test_transformed_gc.py
Log:
Started generic cloning based on GC support.  This should provide
exactly what is needed by the simple thread cloning approach
discussed on pypy-dev.  Doing it at the GC level also looks like
a good plan.


Modified: pypy/dist/pypy/rpython/lltypesystem/lloperation.py
==============================================================================
--- pypy/dist/pypy/rpython/lltypesystem/lloperation.py	(original)
+++ pypy/dist/pypy/rpython/lltypesystem/lloperation.py	Fri May 19 13:28:09 2006
@@ -317,6 +317,10 @@
     'gc_protect':           LLOp(),
     'gc_unprotect':         LLOp(),    
     'gc_reload_possibly_moved': LLOp(),
+    # experimental operations in support of thread cloning, only
+    # implemented by the Mark&Sweep GC
+    'gc_x_swap_list':       LLOp(),
+    'gc_x_clone':           LLOp(canraise=(MemoryError,)),
 
     # __________ stackless operation(s) __________
 

Modified: pypy/dist/pypy/rpython/lltypesystem/test/test_lloperation.py
==============================================================================
--- pypy/dist/pypy/rpython/lltypesystem/test/test_lloperation.py	(original)
+++ pypy/dist/pypy/rpython/lltypesystem/test/test_lloperation.py	Fri May 19 13:28:09 2006
@@ -21,6 +21,8 @@
 
 def test_llinterp_complete():
     for opname in LL_OPERATIONS:
+        if opname.startswith('gc_x_'):
+            continue   # ignore experimental stuff
         assert opname in LL_INTERP_OPERATIONS
 
 def test_llop():

Modified: pypy/dist/pypy/rpython/memory/gc.py
==============================================================================
--- pypy/dist/pypy/rpython/memory/gc.py	(original)
+++ pypy/dist/pypy/rpython/memory/gc.py	Fri May 19 13:28:09 2006
@@ -12,6 +12,9 @@
 int_size = lltypesimulation.sizeof(lltype.Signed)
 gc_header_two_ints = 2*int_size
 
+X_CLONE = lltype.GcStruct('CloneData', ('gcobjectptr', llmemory.GCREF),
+                                       ('malloced_list', llmemory.Address))
+
 class GCError(Exception):
     pass
 
@@ -281,6 +284,82 @@
         hdr.typeid = typeid << 1
     init_gc_object_immortal = init_gc_object
 
+    # experimental support for thread cloning
+    def x_swap_list(self, malloced_list):
+        # Swap the current malloced_objects linked list with another one.
+        # All malloc'ed objects are put into the current malloced_objects
+        # list; this is a way to separate objects depending on when they
+        # were allocated.
+        current = llmemory.cast_ptr_to_adr(self.malloced_objects)
+        self.malloced_objects = llmemory.cast_adr_to_ptr(malloced_list,
+                                                         self.HDRPTR)
+        return current
+
+    def x_clone(self, clonedata):
+        # Recursively clone the gcobject and everything it points to,
+        # directly or indirectly -- but stops at objects that are not
+        # in the malloced_list.  The gcobjectptr and the malloced_list
+        # fields of clonedata are adjusted to refer to the result.
+        size_gc_header = self.gcheaderbuilder.size_gc_header
+        oldobjects = self.AddressLinkedList()
+        hdr = llmemory.cast_adr_to_ptr(clonedata.malloced_list, self.HDRPTR)
+        while hdr:
+            next = hdr.next
+            hdr.typeid |= 1    # mark all objects from malloced_list
+            hdr.next = lltype.nullptr(self.HDR)  # abused to point to the copy
+            oldobjects.append(llmemory.cast_ptr_to_adr(hdr))
+            hdr = next
+
+        # a stack of addresses of places that still points to old objects
+        # and that must possibly be fixed to point to a new copy
+        stack = self.AddressLinkedList()
+        stack.append(llmemory.cast_ptr_to_adr(clonedata)
+                     + llmemory.offsetof(X_CLONE, 'gcobjectptr'))
+        newobjectlist = lltype.nullptr(self.HDR)
+        while stack.non_empty():
+            gcptr_addr = stack.pop()
+            oldobj_addr = gcptr_addr.address[0]
+            oldhdr = llmemory.cast_adr_to_ptr(oldobj_addr - size_gc_header,
+                                              self.HDRPTR)
+            typeid = oldhdr.typeid
+            if not (typeid & 1):
+                continue   # ignore objects that were not in the malloced_list
+            newhdr = oldhdr.next      # abused to point to the copy
+            if not newhdr:
+                typeid >>= 1
+                if self.is_varsize(typeid):
+                    raise NotImplementedError
+                else:
+                    size = self.fixed_size(typeid)
+                    newmem = raw_malloc(size_gc_header + size)
+                    newhdr = llmemory.cast_adr_to_ptr(newmem, self.HDRPTR)
+                    newhdr.typeid = typeid << 1
+                    newhdr.next = newobjectlist
+                    newobjectlist = newhdr
+                    newobj_addr = newmem + size_gc_header
+                    raw_memcopy(oldobj_addr, newobj_addr, size)
+                    offsets = self.offsets_to_gc_pointers(typeid)
+                    i = 0
+                    while i < len(offsets):
+                        pointer_addr = newobj_addr + offsets[i]
+                        stack.append(pointer_addr)
+                        i += 1
+                oldhdr.next = newhdr
+            newobj_addr = llmemory.cast_ptr_to_adr(newhdr) + size_gc_header
+            gcptr_addr.address[0] = newobj_addr
+
+        clonedata.malloced_list = llmemory.cast_ptr_to_adr(newobjectlist)
+
+        # re-create the original linked list
+        next = lltype.nullptr(self.HDR)
+        while oldobjects.non_empty():
+            hdr = llmemory.cast_adr_to_ptr(oldobjects.pop(), self.HDRPTR)
+            hdr.typeid &= ~1   # reset the mark bit
+            hdr.next = next
+            next = hdr
+        oldobjects.delete()
+
+
 class SemiSpaceGC(GCBase):
     _alloc_flavor_ = "raw"
 

Modified: pypy/dist/pypy/rpython/memory/gctransform.py
==============================================================================
--- pypy/dist/pypy/rpython/memory/gctransform.py	(original)
+++ pypy/dist/pypy/rpython/memory/gctransform.py	Fri May 19 13:28:09 2006
@@ -868,25 +868,34 @@
                                       inline = True)
 
         classdef = bk.getuniqueclassdef(GCClass)
-        s_gcdata = annmodel.SomeInstance(classdef)
+        s_gc = annmodel.SomeInstance(classdef)
         s_gcref = annmodel.SomePtr(llmemory.GCREF)
         self.malloc_fixedsize_ptr = getfn(
             GCClass.malloc_fixedsize.im_func,
-            [s_gcdata, annmodel.SomeInteger(nonneg=True),
+            [s_gc, annmodel.SomeInteger(nonneg=True),
              annmodel.SomeInteger(nonneg=True),
              annmodel.SomeBool()], s_gcref,
             inline = True)
         self.malloc_varsize_ptr = getfn(
             GCClass.malloc_varsize.im_func,
-            [s_gcdata] + [annmodel.SomeInteger(nonneg=True) for i in range(5)]
+            [s_gc] + [annmodel.SomeInteger(nonneg=True) for i in range(5)]
             + [annmodel.SomeBool()], s_gcref)
         self.collect_ptr = getfn(GCClass.collect.im_func,
-            [s_gcdata], annmodel.s_None)
+            [s_gc], annmodel.s_None)
 
         statics_s = (annmodel.SomeInteger(),)*GCClass.STATISTICS_NUMBERS
         self.statistics_ptr = getfn(GCClass.statistics.im_func,
-                                    [s_gcdata], annmodel.SomeTuple(statics_s))
-                                   
+                                    [s_gc], annmodel.SomeTuple(statics_s))
+
+        # experimental gc_x_* operations
+        self.x_swap_list_ptr = getfn(GCClass.x_swap_list.im_func,
+                                     [s_gc, annmodel.SomeAddress()],
+                                     annmodel.SomeAddress())
+        self.x_clone_ptr = getfn(GCClass.x_clone.im_func,
+                                 [s_gc,
+                                  annmodel.SomePtr(lltype.Ptr(gc.X_CLONE))],
+                                 annmodel.s_None)
+
         annhelper.finish()   # at this point, annotate all mix-level helpers
         annhelper.backend_optimize()
 
@@ -1153,6 +1162,22 @@
                                         block.operations.index(op))
         return ops
 
+    def replace_gc_x_swap_list(self, op, livevars, block):
+        [v_malloced] = op.args
+        newop = SpaceOperation("direct_call",
+                               [self.x_swap_list_ptr, self.c_const_gc,
+                                                      v_malloced],
+                               op.result)
+        return [newop]
+
+    def replace_gc_x_clone(self, op, livevars, block):
+        [v_clonedata] = op.args
+        newop = SpaceOperation("direct_call",
+                               [self.x_clone_ptr, self.c_const_gc,
+                                                  v_clonedata],
+                               op.result)
+        return [newop]
+
     def push_alive_nopyobj(self, var):
         return []
 

Modified: pypy/dist/pypy/rpython/memory/test/test_transformed_gc.py
==============================================================================
--- pypy/dist/pypy/rpython/memory/test/test_transformed_gc.py	(original)
+++ pypy/dist/pypy/rpython/memory/test/test_transformed_gc.py	Fri May 19 13:28:09 2006
@@ -156,11 +156,12 @@
 
 from pypy.translator.c import gc
 from pypy.annotation import model as annmodel
-from pypy.rpython.lltypesystem import lltype
+from pypy.rpython.lltypesystem import lltype, llmemory
 from pypy.rpython.memory import gctransform
 from pypy.rpython.lltypesystem.lloperation import llop
 from pypy.rpython.lltypesystem import lltype
 from pypy.rpython.memory.support import INT_SIZE
+from pypy.rpython.memory.gc import X_CLONE
 from pypy import conftest
 
 
@@ -292,6 +293,40 @@
         heap_size = statistics().item0
         assert heap_size < 16000 * INT_SIZE / 4 # xxx
 
+    def test_cloning(self):
+        py.test.skip("in-progress")
+        B = lltype.GcStruct('B', ('x', lltype.Signed))
+        A = lltype.GcStruct('A', ('b', lltype.Ptr(B)))
+        def make(n):
+            b = lltype.malloc(B)
+            b.x = n
+            a = lltype.malloc(A)
+            a.b = b
+            return a
+        def func():
+            a1 = make(111)
+            # start recording mallocs in a new list
+            oldlist = llop.gc_x_swap_list(llmemory.Address, llmemory.NULL)
+            # the following a2 goes into the new list
+            a2 = make(222)
+            # now put the old list back and get the new list
+            newlist = llop.gc_x_swap_list(llmemory.Address, oldlist)
+            a3 = make(333)
+            # clone a2
+            a2ref = lltype.cast_opaque_ptr(llmemory.GCREF, a2)
+            clonedata = lltype.malloc(X_CLONE)
+            clonedata.gcobjectptr = a2ref
+            clonedata.malloced_list = newlist
+            llop.gc_x_clone(lltype.Void, clonedata)
+            a2copyref = clonedata.gcobjectptr
+            a2copy = lltype.cast_opaque_ptr(lltype.Ptr(A), a2copyref)
+            a2copy.b.x = 444
+            return a1.b.x * 1000000 + a2.b.x * 1000 + a3.b.x
+
+        run = self.runner(func)
+        res = run([])
+        assert res == 111222333
+
 
 class TestStacklessMarkSweepGC(TestMarkSweepGC):
 


From ericvrp at codespeak.net  Fri May 19 14:38:57 2006
From: ericvrp at codespeak.net (ericvrp at codespeak.net)
Date: Fri, 19 May 2006 14:38:57 +0200 (CEST)
Subject: [pypy-svn] r27472 - pypy/extradoc/sprintinfo/ddorf2006
Message-ID: <20060519123857.5B7441006E@code0.codespeak.net>

Author: ericvrp
Date: Fri May 19 14:38:55 2006
New Revision: 27472

Modified:
   pypy/extradoc/sprintinfo/ddorf2006/people.txt
Log:
my ddorf dates, for the 7th I have not book a train yet.


Modified: pypy/extradoc/sprintinfo/ddorf2006/people.txt
==============================================================================
--- pypy/extradoc/sprintinfo/ddorf2006/people.txt	(original)
+++ pypy/extradoc/sprintinfo/ddorf2006/people.txt	Fri May 19 14:38:55 2006
@@ -12,7 +12,7 @@
 Armin Rigo           ?              private
 Holger Krekel        1st-9th        ?
 Carl Friedrich Bolz  nope :-)       private
-Eric van Riet Paap   ?              ?
+Eric van Riet Paap   2nd-4th + 7th? ?
 Maciej Fijalkowski   3rd-9th        cfbolz
 Anders Chrigstroem   1st - 9th      ?
 Samuele Pedroni      1st - 9th      ?


From arigo at codespeak.net  Fri May 19 16:19:47 2006
From: arigo at codespeak.net (arigo at codespeak.net)
Date: Fri, 19 May 2006 16:19:47 +0200 (CEST)
Subject: [pypy-svn] r27477 - pypy/extradoc/talk/dls2006
Message-ID: <20060519141947.073A21006B@code0.codespeak.net>

Author: arigo
Date: Fri May 19 16:19:46 2006
New Revision: 27477

Added:
   pypy/extradoc/talk/dls2006/
   pypy/extradoc/talk/dls2006/outline.txt   (contents, props changed)
Log:
Pre-preliminary outline for OOPSLA/DLS


Added: pypy/extradoc/talk/dls2006/outline.txt
==============================================================================
--- (empty file)
+++ pypy/extradoc/talk/dls2006/outline.txt	Fri May 19 16:19:46 2006
@@ -0,0 +1,43 @@
+************************************************************
+                       Cool Title Here
+************************************************************
+
+
+Introduction
+============
+
+High-level architecture, VM portability+flexibility goals with comparisons
+
+System programming with Python
+==============================
+
+* PyPy in RPython
+* RTyper helpers (ll, oo type systems)
+* GC
+
+Manipulatable, e.g. as in Stackless Transform
+
+Type inference details
+======================
+
+Flow space, annotator overviews
+
+Not very precise, no automatic polymorphism, but easy to control, fast, easy
+and to reuse with different type systems: RPython, ll, oo, rctypes,
+BTA (binding-time analysis for the JIT)...  easy custom specializations
+
+Future work
+===========
+
+JIT
+
+Related work
+============
+
+* Squeak
+* Jikes RVM
+
+Conclusion
+==========
+
+Works, reasonably efficient, quite confusing at times


From mwh at codespeak.net  Fri May 19 16:43:41 2006
From: mwh at codespeak.net (mwh at codespeak.net)
Date: Fri, 19 May 2006 16:43:41 +0200 (CEST)
Subject: [pypy-svn] r27478 - in pypy/dist/pypy/rpython/lltypesystem: . test
Message-ID: <20060519144341.71D1410060@code0.codespeak.net>

Author: mwh
Date: Fri May 19 16:43:39 2006
New Revision: 27478

Modified:
   pypy/dist/pypy/rpython/lltypesystem/llheap.py
   pypy/dist/pypy/rpython/lltypesystem/llmemory.py
   pypy/dist/pypy/rpython/lltypesystem/test/test_llmemory.py
Log:
implement llmemory.raw_memcopy by using existing code that does the donkey work
in rctypes.


Modified: pypy/dist/pypy/rpython/lltypesystem/llheap.py
==============================================================================
--- pypy/dist/pypy/rpython/lltypesystem/llheap.py	(original)
+++ pypy/dist/pypy/rpython/lltypesystem/llheap.py	Fri May 19 16:43:39 2006
@@ -2,4 +2,5 @@
 
 from pypy.rpython.lltypesystem.lltype import pyobjectptr, malloc, free
 from pypy.rpython.lltypesystem.llmemory import raw_malloc, raw_free
+from pypy.rpython.lltypesystem.llmemory import raw_memcopy
 from pypy.rpython.lltypesystem.llmemory import raw_malloc_usage

Modified: pypy/dist/pypy/rpython/lltypesystem/llmemory.py
==============================================================================
--- pypy/dist/pypy/rpython/lltypesystem/llmemory.py	(original)
+++ pypy/dist/pypy/rpython/lltypesystem/llmemory.py	Fri May 19 16:43:39 2006
@@ -510,6 +510,14 @@
         size = convert_offset_to_int(size)
     return size
 
+def raw_memcopy(source, dest, size):
+    source = source.get()
+    dest = dest.get()
+    # this check would be nice...
+    #assert sizeof(lltype.typeOf(source)) == sizeof(lltype.typeOf(dest)) == size
+    from pypy.rpython.rctypes.rmodel import reccopy
+    reccopy(source, dest)
+
 # ____________________________________________________________
 
 class _arena(object):

Modified: pypy/dist/pypy/rpython/lltypesystem/test/test_llmemory.py
==============================================================================
--- pypy/dist/pypy/rpython/lltypesystem/test/test_llmemory.py	(original)
+++ pypy/dist/pypy/rpython/lltypesystem/test/test_llmemory.py	Fri May 19 16:43:39 2006
@@ -392,6 +392,17 @@
     repr(adr)
     str(p_u)
 
+def test_raw_memcopy():
+    T = lltype.GcStruct('T', ('x', lltype.Signed))
+    t1 = lltype.malloc(T)
+    t2 = lltype.malloc(T)
+    t1.x = 1
+    t2.x = 2
+    at1 = cast_ptr_to_adr(t1)
+    at2 = cast_ptr_to_adr(t2)
+    raw_memcopy(at1, at2, sizeof(T))
+    assert t2.x == 1
+
 def test_inlined_substruct():
     T = lltype.Struct('T', ('x', lltype.Signed))
     S1 = lltype.GcStruct('S1', ('t1', T), ('t2', T))


From pedronis at codespeak.net  Fri May 19 16:44:46 2006
From: pedronis at codespeak.net (pedronis at codespeak.net)
Date: Fri, 19 May 2006 16:44:46 +0200 (CEST)
Subject: [pypy-svn] r27479 - pypy/extradoc/talk/dls2006
Message-ID: <20060519144446.782F310063@code0.codespeak.net>

Author: pedronis
Date: Fri May 19 16:44:44 2006
New Revision: 27479

Modified:
   pypy/extradoc/talk/dls2006/outline.txt
Log:
some tweaks



Modified: pypy/extradoc/talk/dls2006/outline.txt
==============================================================================
--- pypy/extradoc/talk/dls2006/outline.txt	(original)
+++ pypy/extradoc/talk/dls2006/outline.txt	Fri May 19 16:44:44 2006
@@ -7,6 +7,7 @@
 ============
 
 High-level architecture, VM portability+flexibility goals with comparisons
+(rigidity, less expressiveness of implementation languages)
 
 System programming with Python
 ==============================
@@ -40,4 +41,7 @@
 Conclusion
 ==========
 
-Works, reasonably efficient, quite confusing at times
+Works, effectively increases flexibility and expressiveness,
+ reasonably efficient, quite confusing at times;
+work in progress, some things are rough and could use more
+streamlined implementations and uniform approaches


From mwh at codespeak.net  Fri May 19 17:06:37 2006
From: mwh at codespeak.net (mwh at codespeak.net)
Date: Fri, 19 May 2006 17:06:37 +0200 (CEST)
Subject: [pypy-svn] r27480 - pypy/extradoc/talk/ep2006
Message-ID: <20060519150637.779F210063@code0.codespeak.net>

Author: mwh
Date: Fri May 19 17:06:36 2006
New Revision: 27480

Added:
   pypy/extradoc/talk/ep2006/
   pypy/extradoc/talk/ep2006/planning.txt   (contents, props changed)
Log:
the plans from yesterday's sync meeting about europython.


Added: pypy/extradoc/talk/ep2006/planning.txt
==============================================================================
--- (empty file)
+++ pypy/extradoc/talk/ep2006/planning.txt	Fri May 19 17:06:36 2006
@@ -0,0 +1,15 @@
+we had a bit of a chat in the pypy-sync meeting on 2006-05-18 about the talks
+we want to give at europython this year.  we decided that we might give up to 4
+talks:
+
+    1. an introductory talk, probably based on michael's talk from the accu
+       conference (but likely a bit shorter)
+
+    2. a "what pypy can do for you" talk, covering the ext-compiler, stackless,
+       etc.
+
+    3. an architecture session, similar to that held at pycon this year.
+
+    4. a talk on the methodology side of the project.
+
+In addition Eric will probably give a lightning talk about the JS backend.


From tismer at codespeak.net  Fri May 19 17:12:10 2006
From: tismer at codespeak.net (tismer at codespeak.net)
Date: Fri, 19 May 2006 17:12:10 +0200 (CEST)
Subject: [pypy-svn] r27481 - in pypy/dist/pypy: module/_pickle_support
	objspace/std
Message-ID: <20060519151210.B73AD10063@code0.codespeak.net>

Author: tismer
Date: Fri May 19 17:12:09 2006
New Revision: 27481

Modified:
   pypy/dist/pypy/module/_pickle_support/maker.py
   pypy/dist/pypy/objspace/std/dicttype.py
Log:
showing a way to produce an unpickled object.
Note that in this special case, we need to do something
different, anyway. Please use what you find in prickelpit.c

Modified: pypy/dist/pypy/module/_pickle_support/maker.py
==============================================================================
--- pypy/dist/pypy/module/_pickle_support/maker.py	(original)
+++ pypy/dist/pypy/module/_pickle_support/maker.py	Fri May 19 17:12:09 2006
@@ -35,30 +35,19 @@
     return space.call_args(w_type, __args__)
 method_new.unwrap_spec = [ObjSpace, Arguments]
 
-#XXX this does not work yet
-def dictiter_new(space, w_dictitertype, __args__=None):
-    raise Exception('No dictiter_new (pickle support) yet')
-    print "dictiter_new here 0)", space, w_dictitertype, __args__
-    print "XXX", str(dictiter_typedef)
-    if False:
-        w_type = space.gettypeobject(dictiter_typedef)
-        print "dictiter_new here 2)", w_type
-        a = space.call_args(w_type, __args__)
-        print "dictiter_new here 3)", a
-        return a
-    else:
-        from pypy.objspace.std.dictobject import W_DictIterObject
-        print "dictiter_new here 1)", space, w_dictitertype, __args__
-        #import pdb;pdb.set_trace()
-        if space.is_true(space.issubtype(w_dictitertype, W_DictIterObject)):
-            w_obj = space.allocate_instance(W_DictIterObject, w_dictitertype)
-            print "dictiter_new here 2)", w_obj
-            W_DictIterObject.__init__(w_obj, space)
-            print "dictiter_new here 3)", w_obj
-            return w_obj
-dictiter_new.unwrap_spec = [ObjSpace, W_Root, Arguments]
+def dictiter_new(space, __args__):
+    from pypy.objspace.std.dictobject import W_DictIterObject
+    print "dictiter_new here 1)", space, w_dictitertype, __args__
+    w_type = space.gettypeobject(dictiter_typedef)
+    w_obj = space.allocate_instance(W_DictIterObject, w_type)
+    print "dictiter_new here 2)", w_obj
+    # XXX W_DictIterObject.__init__(w_obj, space)
+    # this is wrong, but we need to produce something different, anyway
+    print "dictiter_new here 3)", w_obj
+    return w_obj
+dictiter_new.unwrap_spec = [ObjSpace, Arguments]
 
-#XXX this doesn't work either
+#XXX this doesn't work yet
 def seqiter_new(space, w_seqitertype, __args__):
     raise Exception('No seqiter_new (pickle support) yet')
     print "seqiter_new here 1)", space, __args__

Modified: pypy/dist/pypy/objspace/std/dicttype.py
==============================================================================
--- pypy/dist/pypy/objspace/std/dicttype.py	(original)
+++ pypy/dist/pypy/objspace/std/dicttype.py	Fri May 19 17:12:09 2006
@@ -154,6 +154,6 @@
 
 dictiter_typedef = StdTypeDef("dictionaryiterator",
     __reduce__ = gateway.interp2app(descr_dictiter__reduce__,
-                           unwrap_spec=[gateway.ObjSpace,gateway.W_Root]),
+                           unwrap_spec=[gateway.ObjSpace, gateway.W_Root]),
     )
 #note: registering in dictobject.py


From arigo at codespeak.net  Fri May 19 17:15:24 2006
From: arigo at codespeak.net (arigo at codespeak.net)
Date: Fri, 19 May 2006 17:15:24 +0200 (CEST)
Subject: [pypy-svn] r27482 - in pypy/dist/pypy/rpython: lltypesystem
	lltypesystem/test memory/test
Message-ID: <20060519151524.D971510063@code0.codespeak.net>

Author: arigo
Date: Fri May 19 17:15:23 2006
New Revision: 27482

Modified:
   pypy/dist/pypy/rpython/lltypesystem/llmemory.py
   pypy/dist/pypy/rpython/lltypesystem/test/test_llmemory.py
   pypy/dist/pypy/rpython/memory/test/test_transformed_gc.py
Log:
(pedronis, arigo)

Allow addr.address[0] = ... to write into a pointer field.
Some renamings.  Now test_cloning works :-)


Modified: pypy/dist/pypy/rpython/lltypesystem/llmemory.py
==============================================================================
--- pypy/dist/pypy/rpython/lltypesystem/llmemory.py	(original)
+++ pypy/dist/pypy/rpython/lltypesystem/llmemory.py	Fri May 19 17:15:23 2006
@@ -396,18 +396,23 @@
         addr = self.addr
         if index != 0:
             addr += ItemOffset(addr.ref().type(), index)
-        return self.convert(addr.get())
+        return self.erase_type(addr.get())
 
     def __setitem__(self, index, value):
+        assert lltype.typeOf(value) == self.TYPE
         addr = self.addr
         if index != 0:
             addr += ItemOffset(addr.ref().type(), index)
-        addr.set(value)
+        addr.set(self.unerase_type(addr.ref().type(), value))
 
-    def convert(self, value):
+    def erase_type(self, value):
         assert lltype.typeOf(value) == self.TYPE
         return value
 
+    def unerase_type(self, TARGETTYPE, value):
+        assert lltype.typeOf(value) == TARGETTYPE
+        return value
+
 
 class _signed_fakeaccessor(_fakeaccessor):
     TYPE = lltype.Signed
@@ -415,17 +420,10 @@
 class _char_fakeaccessor(_fakeaccessor):
     TYPE = lltype.Char
 
-    def convert(self, value):
-        # hack to try to interpret the items of an array of bytes as chars
-        if lltype.typeOf(value) == lltype.Signed:
-            value = chr(value)
-        assert lltype.typeOf(value) == lltype.Char
-        return value
-
 class _address_fakeaccessor(_fakeaccessor):
     TYPE = Address
 
-    def convert(self, value):
+    def erase_type(self, value):
         if isinstance(value, lltype._ptr):
             return value._cast_to_adr()
         elif lltype.typeOf(value) == Address:
@@ -433,6 +431,14 @@
         else:
             raise TypeError(value)
 
+    def unerase_type(self, TARGETTYPE, value):
+        if TARGETTYPE == Address:
+            return value
+        elif isinstance(TARGETTYPE, lltype.Ptr):
+            return cast_adr_to_ptr(value, TARGETTYPE)
+        else:
+            raise TypeError(TARGETTYPE, value)
+
 
 fakeaddress.signed = property(_signed_fakeaccessor)
 fakeaddress.char = property(_char_fakeaccessor)

Modified: pypy/dist/pypy/rpython/lltypesystem/test/test_llmemory.py
==============================================================================
--- pypy/dist/pypy/rpython/lltypesystem/test/test_llmemory.py	(original)
+++ pypy/dist/pypy/rpython/lltypesystem/test/test_llmemory.py	Fri May 19 17:15:23 2006
@@ -144,6 +144,18 @@
     adr1000 = (adr + ArrayItemsOffset(A) + ItemOffset(lltype.Char, 1000))
     assert adr1000.char[-997] == '+'
 
+    T = lltype.FixedSizeArray(lltype.Char, 10)
+    S = lltype.GcStruct('S', ('z', lltype.Ptr(T)))
+    s = lltype.malloc(S)
+    s.z = lltype.malloc(T, immortal=True)
+    adr = cast_ptr_to_adr(s)
+    assert (adr + offsetof(S, 'z')).address[0] == cast_ptr_to_adr(s.z)
+    (adr + offsetof(S, 'z')).address[0] = NULL
+    assert s.z == lltype.nullptr(T)
+    t = lltype.malloc(T, immortal=True)
+    (adr + offsetof(S, 'z')).address[0] = cast_ptr_to_adr(t)
+    assert s.z == t
+
 def test_fakeadr_eq():
     S = lltype.GcStruct("S", ("x", lltype.Signed), ("y", lltype.Signed))
     s = lltype.malloc(S)

Modified: pypy/dist/pypy/rpython/memory/test/test_transformed_gc.py
==============================================================================
--- pypy/dist/pypy/rpython/memory/test/test_transformed_gc.py	(original)
+++ pypy/dist/pypy/rpython/memory/test/test_transformed_gc.py	Fri May 19 17:15:23 2006
@@ -294,7 +294,6 @@
         assert heap_size < 16000 * INT_SIZE / 4 # xxx
 
     def test_cloning(self):
-        py.test.skip("in-progress")
         B = lltype.GcStruct('B', ('x', lltype.Signed))
         A = lltype.GcStruct('A', ('b', lltype.Ptr(B)))
         def make(n):


From mwh at codespeak.net  Fri May 19 17:19:53 2006
From: mwh at codespeak.net (mwh at codespeak.net)
Date: Fri, 19 May 2006 17:19:53 +0200 (CEST)
Subject: [pypy-svn] r27483 - pypy/extradoc/minute
Message-ID: <20060519151953.27B2810063@code0.codespeak.net>

Author: mwh
Date: Fri May 19 17:19:51 2006
New Revision: 27483

Added:
   pypy/extradoc/minute/pypy-sync-2006-05-18.txt   (contents, props changed)
Log:
preliminary minutes for yesterday's meeting.


Added: pypy/extradoc/minute/pypy-sync-2006-05-18.txt
==============================================================================
--- (empty file)
+++ pypy/extradoc/minute/pypy-sync-2006-05-18.txt	Fri May 19 17:19:51 2006
@@ -0,0 +1,216 @@
+pypy-sync 18th May 2006, 17:30 - 18:00 (UTC+2)
+=====================================================
+
+attendants: michael (mod and minutes), anto (beforehand), samuele,
+            carl, eric, arre, armin, anders, holger, nik
+
+* activity reports: everybody posted, see log below. 
+
+* oopsla paper and europython submissions
+
+  We talked about the requirements for a paper at the Dynamic Language
+  Symposium at OOPSLA.  There was discussion about whether we could
+  (probably) or should (probably not) reuse material from our WP05 reports.
+  It was agreed that Samuele and Armin would spend a little time working on
+  an outline before Samuele goes on holiday on Monday.  This is in
+   so far.
+
+  The deadline is June 1.
+
+  We also talked about how many talks we should submit to EuroPython
+  this year.  I've summarized the decisions in
+  .
+
+* state of the world
+
+  We didn't really get to this in any meaningful way.  Try again next week?
+
+* any other business?
+
+  Samuele noted that translation with --new-stackless is very, very slow.
+  Michael responded that he was running a version with profiling using
+  lsprof to see if he could find any obvious stupidities.  This translation
+  has still not finished, nearly 24 hours later, so it must be breaking all
+  known records for longest translation...
+
+IRC logs 
+-------------
+
+::
+
+    [16:22]  uhm... I've to go out at 17:30
+    [16:22]  here is my report:
+    [16:22]  LAST: completed ootypesystem string; broken the translation few times :-)
+    [16:22]  NEXT: string support in gencli; some university stuff
+    [16:22]  BLOCKERS: None
+    [16:22]  see you later
+    [16:23] antocuni (n=chatzill at 217.201.198.80) left irc: "Chatzilla 0.9.72 [Firefox 1.5/2005120619]"
+    [16:27] hpk (n=hpk at codespeak.net) joined #pypy-sync.
+    [16:29] nikh (n=nikh at 102-187.1-85.cust.bluewin.ch) joined #pypy-sync.
+    [16:30] ericvrp (n=ericvrp at ericvrp.demon.nl) joined #pypy-sync.
+    [16:31]  hello everyone
+    [16:31]  hi all
+    [16:31]  hi!
+    [16:31]  hi!
+    [16:31]  howdy
+    [16:32] arigo (n=arigo at c-1f8b70d5.022-54-67626719.cust.bredbandsbolaget.se) joined #pypy-sync.
+    [16:32]  so, activity reports from everyone please
+    [16:32] Nick change: mwh -> not-stakkars
+    [16:32]  PREV: OWL reasoner, recreation with my family
+    [16:32]  DONE: coached Stephan on app-level Stackless, helped Eric with
+    [16:32]  the pickling support, analyzed many flow-graphs
+    [16:32]  NEXT: support for costate for app-level, more coaching, implement
+    [16:32]  a few demo picklers, investigate more on feasibility of the
+    [16:32]  pickling design doc, prepare for Iceland sprint
+    [16:32]  BLOCK: I cannot estimate what will come out of it. I'm not
+    [16:32]  sure if I can find a way to avoid pickling of many records.
+    [16:32]  NEXT: More OWL
+    [16:32] Nick change: not-stakkars -> mwh
+    [16:32]  block : -
+    [16:33]  LAST: uni stuff mostly, some small things
+    [16:33]  NEXT: __del__ support??
+    [16:33]  BLOCKERS: time constraints
+    [16:33]  LAST: this and that, weakrefs, stackless
+    [16:33]  NEXT: not sure, some performance measurements
+    [16:33]  BLOCKERS: hard to keep up!
+    [16:33]  LAST: pypy duesseldorf and some other pypy orga + plannings, new pypy build host setup, non-pypy
+    [16:33]  NEXT: make pypy build host available, SoC/EU models, non-pypy
+    [16:33]  BLOCKERS: -
+    [16:33]  LAST: integrate stackless and GC
+    [16:33]  NEXT: oopsla paper, thread cloning
+    [16:33]  BLOCKERS: -
+    [16:33]  LAST: non-pypy
+    [16:33]  NEXT: non-pypy
+    [16:33]  BLOCKERS: none, but i'm very deep in university stuff
+    [16:34]  pedronis? arre?
+    [16:34]  LAST: rctypes primitive types with arre, gc, stackless stuff with Armin, bug fixing
+    [16:34]  NEXT: vacation, no internet as least until thurs
+    [16:34]  BLOCKERS: -
+    [16:34]  ericvrp?
+    [16:34]  on moment
+    [16:34]  PREV: rctypes
+    [16:34]  NEXT: Mostly vacation
+    [16:34]  BLOCKERS: -
+    [16:34]  LAST: slow progress with pickling + dusting of genllvm + little genjs documentation
+    [16:34]  NEXT: more pickling and some distractions
+    [16:34]  BLOCKERS: don't know
+    [16:35]  so the first topic is the oopsla paper
+    [16:35]  (with an additional subtopic of "europython papers")
+    [16:36]  the deadline is june 1
+    [16:36]  arigo, pedronis: i think you talked a bit about this yesterday?
+    [16:38] Action: mwh bounces
+    [16:38]  samuele?  want to say a word about it?
+    [16:38]  i am curious if you considered a research or an experience paper
+    [16:38]  or both :)
+    [16:39]  well, I think the idea is to write an overview paper, describing how basic techniques: type inference/ abstract interpreation
+    [16:39]  based on the d05 papers?
+    [16:40]  i mean the work package 5 papers
+    [16:40]  shortly and then seeing how this are repeatedly used through the tool chain and to impose types on our singled langague
+    [16:40]  and what can we achieve with this
+    [16:40]  hpk: much more overviewish, I think
+    [16:41]  s/singled .../single not statically typed language
+    [16:41]  do we know e.g. how long papers are expected to be?
+    [16:41]  mwh: max 12 pages in PDF
+    [16:41]  and they require the "ACM format"
+    [16:42]  right
+    [16:42]  that's just a style file with the latex, i don't think that's too big a deal
+    [16:42]  ... cfbolz ? :)
+    [16:42]  :-)
+    [16:42]  we will see :-)
+    [16:43]  well, with 12 pages, is hard not to be overviewish
+    [16:43]  right
+    [16:43]  and unless we focused on a single thing
+    [16:43]  and even then
+    [16:43]  we do not have the problem that we couldn't reuse stuff from existing reports though
+    [16:43]  because none of them was published in their sense, or is that not correct?
+    [16:43]  I think it will read differently
+    [16:44]  but yes copying long chunks is not a good idea
+    [16:44]  yip
+    [16:44]  i think that's correct, but possibly not that relevant
+    [16:44]  also I'm not sure we can
+    [16:44]  under the 12 pages constraint
+    [16:44]  we really need to write a fresh text
+    [16:45]  we cannot cram the wp05 report in it
+    [16:45]  which is more than 20 pages
+    [16:45]  so, next question: who writes it
+    [16:45]  pedronis is on holiday next week
+    [16:46]  so arigo and ... ?
+    [16:46]  pedronis: sure, i understood that point (although i am not as sure as you that we cannot use anything of what we already have, including graphics etc.)
+    [16:46]  I can possibly help a bit after next thursday
+    [16:46]  ok
+    [16:46]  or before monday
+    [16:46]  would be nice to have the bones of a report before then
+    [16:46]  oh
+    [16:47]  maybe you and arigo could come up with an outline soon-ish?
+    [16:47]  arigo: we may try to write an outline tomorrow
+    [16:47] Action: hpk thinks he can proof-read and possibly help end next week/early the following
+    [16:48]  ok for me
+    [16:48]  but again, research or experience paper?
+    [16:48]  they seem to make this distinction
+    [16:48]  sounds more like research to me
+    [16:48]  I think experience papers are more about using a language or some features
+    [16:49]  yes research i think
+    [16:49]  ok
+    [16:49]  if we can hurry on
+    [16:49]  how many talks do we want to submit to europython?
+    [16:50]  hpk: is bea going to do a talk in the agility track?
+    [16:50]  mwh: quite likely, yes, i meet her in 10 minutes
+    [16:50]  hpk: coool
+    [16:50]  do we think there's still a market for an introductory talk?
+    [16:50]  i think there probably is
+    [16:51]  mwh: your accu talk is a 80% base talk for that, i'd think
+    [16:51]  it's fairly long though
+    [16:51]  but i guess, do we want to do something else as well?
+    [16:52]  one on the ext-compiler?
+    [16:52]  now comes the potentially interesting talk :-)
+    [16:52]  hpk: that might be good, yes
+    [16:53]  what about the pypy archsession from Pycon?
+    [16:53]  we should have something for the language track
+    [16:54]  the intersection between pycon and EP is not that large, so doing the arch-session + introductory talk (+ maybe ext-compiler) would make sense IMO, but what do you all think?
+    [16:54]  hpk: maybe i'm getting skeptical about the usefulness of that talk
+    [16:54]  I was thinking of giving a pypy-js/genjs talk but there has been to little progress/things to show to make it worth while
+    [16:54]  arigo: it did receive quite positive feedback as far as i heard it, do you know/feel differently?
+    [16:55]  hpk: no, good then
+    [16:55]  I was thinking that it should soon be time to present a language talk
+    [16:55]  about the new language-visible features we can have in PyPy
+    [16:56]  right
+    [16:56]  a "pypy features" talk would be well received, i'd guess
+    [16:56]  and maybe get people away from the speed thing
+    [16:56]  yes, i think so too
+    [16:57]  four pypy related talks might be a bit much though :)
+    [16:57]  yes, I'm worrying a bit that pypy is seen mostly as a large complicated architecture
+    [16:57]  ah ah. people will never get away from the speed thing
+    [16:57]  arigo: you don't worry that it actually _is_ a complicated arch, right? :)
+    [16:57]  never :-)
+    [16:57]  is quite simple in some sense
+    [16:58]  some swiss sense
+    [16:58]  :-)
+    [16:58]  anyway, so let's agree on how to proceed there maybe next week?
+    [16:58]  so, um, we're running out of time
+    [16:58]  well, maybe this could go together with the ext-compiler
+    [16:59]  arigo: yes, pypy features should have 10 minutes about the ext-compiler because that's probably the most real thing
+    [16:59]  pypy agility + pypy intro + pypy features
+    [16:59]  sounds like a plan for now
+    [16:59]  "agility" or "architecture" ?
+    [16:59]  + maybe pypy arch
+    [16:59]  pypy bea/agility
+    [16:59]  is what mwh meant
+    [16:59]  ok
+    [16:59]  pypy bea then :)
+    [16:59]  :-)
+    [17:00]  i think doing the state of the pypy universe in 1 minute is a bit of a stretch
+    [17:00]  "confusing"
+    [17:00]  any other business?
+    [17:00]  ericvrp: but i think a pypy/js focused talk would also make some sense - in the web track :)
+    [17:00]  new-stackless translation is veeeeeery slow
+    [17:00]  i'm profiling now
+    [17:01]  ericvrp: indeed, maybe with fijal even?
+    [17:01]  hpk, the problem is I can not point people to some concrete examples, so it's a bit vague IMO
+    [17:01]  we need to kill the defaults assumption in lltype, we may gain some speed in the gcs
+    [17:01]  ericvrp: maybe, but you do have code that runs in a browser
+    [17:02]  well yes, how many minutes should such a talk be ?
+    [17:02]  well, 30 minutes is the shortest you can do :)
+    [17:03]  there are always lightning talks if you don't want to commit to any results :)
+    [17:03]  I have the feeling that would be better. Real work on genjs will start after europython
+    [17:04]  ok
+    [17:04]  so unless there's anything else, i'd like to close the meeting


From ericvrp at codespeak.net  Fri May 19 17:22:09 2006
From: ericvrp at codespeak.net (ericvrp at codespeak.net)
Date: Fri, 19 May 2006 17:22:09 +0200 (CEST)
Subject: [pypy-svn] r27484 - pypy/dist/pypy/module/_pickle_support
Message-ID: <20060519152209.8968E10063@code0.codespeak.net>

Author: ericvrp
Date: Fri May 19 17:22:02 2006
New Revision: 27484

Modified:
   pypy/dist/pypy/module/_pickle_support/maker.py
Log:
Removed print's because they would break translation


Modified: pypy/dist/pypy/module/_pickle_support/maker.py
==============================================================================
--- pypy/dist/pypy/module/_pickle_support/maker.py	(original)
+++ pypy/dist/pypy/module/_pickle_support/maker.py	Fri May 19 17:22:02 2006
@@ -37,13 +37,13 @@
 
 def dictiter_new(space, __args__):
     from pypy.objspace.std.dictobject import W_DictIterObject
-    print "dictiter_new here 1)", space, w_dictitertype, __args__
+    #print "dictiter_new here 1)", space, w_dictitertype, __args__
     w_type = space.gettypeobject(dictiter_typedef)
     w_obj = space.allocate_instance(W_DictIterObject, w_type)
-    print "dictiter_new here 2)", w_obj
+    #print "dictiter_new here 2)", w_obj
     # XXX W_DictIterObject.__init__(w_obj, space)
     # this is wrong, but we need to produce something different, anyway
-    print "dictiter_new here 3)", w_obj
+    #print "dictiter_new here 3)", w_obj
     return w_obj
 dictiter_new.unwrap_spec = [ObjSpace, Arguments]
 


From mwh at codespeak.net  Fri May 19 18:39:25 2006
From: mwh at codespeak.net (mwh at codespeak.net)
Date: Fri, 19 May 2006 18:39:25 +0200 (CEST)
Subject: [pypy-svn] r27485 - pypy/dist/pypy/translator/stackless
Message-ID: <20060519163925.D595010063@code0.codespeak.net>

Author: mwh
Date: Fri May 19 18:39:23 2006
New Revision: 27485

Modified:
   pypy/dist/pypy/translator/stackless/frame.py
   pypy/dist/pypy/translator/stackless/transform.py
Log:
AAAAARGH, DO NOT call MixLevelHelperAnnotator.finish() an unbounded number of
times.  This workaround is not especially clean, but the stackless tests pass
so I want to try a translation on snake.  Hopefully it won't take 26 hours :)


Modified: pypy/dist/pypy/translator/stackless/frame.py
==============================================================================
--- pypy/dist/pypy/translator/stackless/frame.py	(original)
+++ pypy/dist/pypy/translator/stackless/frame.py	Fri May 19 18:39:23 2006
@@ -130,7 +130,7 @@
         self.func_or_graph = func_or_graph
         self.frame_types = frame_types
 
-    def compress(self, rtyper):
+    def compress(self, rtyper, mix):
         if self.frame_types:
             bk = rtyper.annotator.bookkeeper
             graph = self.func_or_graph
@@ -148,10 +148,8 @@
             for i in range(len(self.frame_types)):
                 reccopy = self.frame_types[i].reccopy
                 s_header = annmodel.SomePtr(lltype.Ptr(STATE_HEADER))
-                mixlevelannotator = MixLevelHelperAnnotator(rtyper)
-                fnptr = mixlevelannotator.delayedfunction(reccopy, [s_header],
+                fnptr = mix.delayedfunction(reccopy, [s_header],
                                                           s_header)
-                mixlevelannotator.finish()
                 result[i]['reccopy'] = fnptr
         else:
             result = []

Modified: pypy/dist/pypy/translator/stackless/transform.py
==============================================================================
--- pypy/dist/pypy/translator/stackless/transform.py	(original)
+++ pypy/dist/pypy/translator/stackless/transform.py	Fri May 19 18:39:23 2006
@@ -229,6 +229,8 @@
                                            lltype.typeOf(null_state))
         self.c_gc_nocollect = model.Constant("gc_nocollect", lltype.Void)
 
+        self.reccopyannotator = MixLevelHelperAnnotator(translator.rtyper)
+
         # register the prebuilt restartinfos
         for restartinfo in frame.RestartInfo.prebuilt:
             self.register_restart_info(restartinfo)
@@ -574,12 +576,13 @@
 
     def register_restart_info(self, restartinfo):
         rtyper = self.translator.rtyper
-        for frame_info_dict in restartinfo.compress(rtyper):
+        for frame_info_dict in restartinfo.compress(rtyper, self.reccopyannotator):
             self.masterarray1.append(frame_info_dict)
 
     def finish(self):
         # compute the final masterarray by copying over the masterarray1,
         # which is a list of dicts of attributes
+        self.reccopyannotator.finish()
         masterarray = lltype.malloc(frame.FRAME_INFO_ARRAY,
                                     len(self.masterarray1),
                                     immortal=True)


From fijal at codespeak.net  Fri May 19 22:45:00 2006
From: fijal at codespeak.net (fijal at codespeak.net)
Date: Fri, 19 May 2006 22:45:00 +0200 (CEST)
Subject: [pypy-svn] r27486 - pypy/dist/pypy/translator/cli
Message-ID: <20060519204500.6844310061@code0.codespeak.net>

Author: fijal
Date: Fri May 19 22:44:24 2006
New Revision: 27486

Modified:
   pypy/dist/pypy/translator/cli/class_.py
   pypy/dist/pypy/translator/cli/database.py
   pypy/dist/pypy/translator/cli/gencli.py
   pypy/dist/pypy/translator/cli/ilgenerator.py
   pypy/dist/pypy/translator/cli/metavm.py
Log:
Generalisation of gencli to support more ootypesystem based backends (like genjs or squeak)


Modified: pypy/dist/pypy/translator/cli/class_.py
==============================================================================
--- pypy/dist/pypy/translator/cli/class_.py	(original)
+++ pypy/dist/pypy/translator/cli/class_.py	Fri May 19 22:44:24 2006
@@ -4,7 +4,7 @@
 class Class(Node):
     def __init__(self, db, classdef):
         self.db = db
-        self.cts = CTS(db)
+        self.cts = db.type_system_class(db)
         self.classdef = classdef
         self.namespace, self.name = self.cts.split_class_name(classdef._name)
 
@@ -52,9 +52,9 @@
         self._ctor()
 
         # lazy import to avoid circular dependencies
-        import pypy.translator.cli.function as function
+        #import pypy.translator.cli.function as function
         for m_name, m_meth in self.classdef._methods.iteritems():
-            f = function.Function(self.db, m_meth.graph, m_name, is_method = True)
+            f = self.db.function_class(self.db, m_meth.graph, m_name, is_method = True)
             f.render(ilasm)
 
         ilasm.end_class()

Modified: pypy/dist/pypy/translator/cli/database.py
==============================================================================
--- pypy/dist/pypy/translator/cli/database.py	(original)
+++ pypy/dist/pypy/translator/cli/database.py	Fri May 19 22:44:24 2006
@@ -3,6 +3,7 @@
 from pypy.translator.cli.class_ import Class
 from pypy.translator.cli.record import Record
 from pypy.rpython.ootypesystem import ootype
+from pypy.translator.cli.opcodes import opcodes
 
 try:
     set
@@ -13,9 +14,12 @@
 CONST_CLASS = 'Constants'
 
 class LowLevelDatabase(object):
-    def __init__(self):
+    def __init__(self, type_system_class = CTS, opcode_dict = opcodes, function_class = Function):
         self._pending_nodes = set()
+        self.opcode_dict = opcode_dict
         self._rendered_nodes = set()
+        self.function_class = function_class
+        self.type_system_class = type_system_class
         self.classes = {} # classdef --> class_name
         self.functions = {} # graph --> function_name
         self.methods = {} # graph --> method_name
@@ -23,7 +27,7 @@
         self.const_names = set()
 
     def pending_function(self, graph):
-        self.pending_node(Function(self, graph))
+        self.pending_node(self.function_class(self, graph))
 
     def pending_class(self, classdef):
         self.pending_node(Class(self, classdef))
@@ -64,6 +68,8 @@
         return '%s.%s::%s' % (CONST_NAMESPACE, CONST_CLASS, name)
 
     def gen_constants(self, ilasm):
+        if not ilasm . show_const ():
+            return
         ilasm.begin_namespace(CONST_NAMESPACE)
         ilasm.begin_class(CONST_CLASS)
 
@@ -77,9 +83,9 @@
         for const, name in self.consts.iteritems():
             const.init(ilasm)
             type_ = const.get_type()
-            ilasm.opcode('stsfld %s %s.%s::%s' % (type_, CONST_NAMESPACE, CONST_CLASS, name))
+            ilasm.set_static_field ( type_, CONST_NAMESPACE, CONST_CLASS, name )
 
-        ilasm.opcode('ret')
+        ilasm.ret()
         ilasm.end_function()
 
         ilasm.end_class()

Modified: pypy/dist/pypy/translator/cli/gencli.py
==============================================================================
--- pypy/dist/pypy/translator/cli/gencli.py	(original)
+++ pypy/dist/pypy/translator/cli/gencli.py	Fri May 19 22:44:24 2006
@@ -7,7 +7,9 @@
 from pypy.translator.cli.class_ import Class
 from pypy.translator.cli.option import getoption
 from pypy.translator.cli.database import LowLevelDatabase
-
+from pypy.translator.cli.cts import CTS
+from pypy.translator.cli.opcodes import opcodes
+from pypy.translator.squeak.node import LoopFinder
 
 class Tee(object):
     def __init__(self, *args):
@@ -23,11 +25,11 @@
                 outfile.close()
 
 class GenCli(object):
-    def __init__(self, tmpdir, translator, entrypoint = None):
+    def __init__(self, tmpdir, translator, entrypoint = None , type_system_class = CTS , opcode_dict = opcodes ):
         self.tmpdir = tmpdir
         self.translator = translator
         self.entrypoint = entrypoint
-        self.db = LowLevelDatabase()
+        self.db = LowLevelDatabase( type_system_class = type_system_class , opcode_dict = opcode_dict )
 
         if entrypoint is None:
             self.assembly_name = self.translator.graphs[0].name
@@ -36,12 +38,12 @@
 
         self.tmpfile = tmpdir.join(self.assembly_name + '.il')
 
-    def generate_source(self):
+    def generate_source(self , asm_class = IlasmGenerator ):
         out = self.tmpfile.open('w')
         if getoption('stdout'):
             out = Tee(sys.stdout, out)
 
-        self.ilasm = IlasmGenerator(out, self.assembly_name)
+        self.ilasm = asm_class(out, self.assembly_name )
         
         # TODO: instance methods that are also called as unbound
         # methods are rendered twice, once within the class and once

Modified: pypy/dist/pypy/translator/cli/ilgenerator.py
==============================================================================
--- pypy/dist/pypy/translator/cli/ilgenerator.py	(original)
+++ pypy/dist/pypy/translator/cli/ilgenerator.py	Fri May 19 22:44:24 2006
@@ -1,3 +1,6 @@
+from pypy.rpython.lltypesystem.lltype import Signed, Unsigned, Void, Bool, Float
+from pypy.rpython.lltypesystem.lltype import SignedLongLong, UnsignedLongLong
+
 class CodeGenerator(object):
     def __init__(self, out, indentstep = 4, startblock = '{', endblock = '}'):
         self._out = out
@@ -40,6 +43,9 @@
         self.code.writeline('.assembly extern pypylib {}')
         self.code.writeline('.assembly %s {}' % name)
 
+    def show_const(self):
+        return True
+
     def close(self):
         self.out.close()
 
@@ -134,6 +140,60 @@
     def new(self, class_):
         self.code.writeline('newobj ' + class_)
 
+    def set_field(self, field_data ):
+        self.opcode('stfld %s %s::%s' % field_data )
+
+    def get_field(self,field_data):
+        self.opcode('ldfld %s %s::%s' % field_data )
+
+    def load_set_field(self, cts_type, name):
+        self.opcode('ldsfld %s %s' % (cts_type, name))
+    
+    def throw(self):
+        self.opcode('throw')
+    
+    def pop(self):
+        self.opcode('pop')
+    
+    def ret(self):
+        self.opcode('ret')
+
+    def castclass(self,cts_type):
+        self.opcode('castclass', cts_type)
+    
+    def load_self(self):
+        self.opcode('ldarg.0')
+    
+    def load_arg(self,v):
+        self.opcode('ldarg', repr(v.name))
+    
+    def load_local(self,v):
+        self.opcode('ldloc', repr(v.name))
+
+    def load_const(self,type_,v):
+        if type_ is Void:
+            pass
+        elif type_ is Bool:
+            self.opcode('ldc.i4', str(int(v)))
+        elif type_ is Float:
+            self.opcode('ldc.r8', repr(v))
+        elif type_ in (Signed, Unsigned):
+            self.opcode('ldc.i4', str(v))
+        elif type_ in (SignedLongLong, UnsignedLongLong):
+            self.opcode('ldc.i8', str(v))
+
+    def store_local ( self , v ):
+        self.opcode('stloc', repr(v.name))
+
+    def set_static_field ( self, type_, CONST_NAMESPACE, CONST_CLASS, name ):
+        self.opcode('stsfld %s %s.%s::%s' % (type_, CONST_NAMESPACE, CONST_CLASS, name))
+
+    def emit ( self , opcode , *args ):
+        self.opcode ( opcode , *args )
+
+    def begin_link ( self ):
+        pass
+
     def opcode(self, opcode, *args):
         self.code.write(opcode + ' ')
         self.code.writeline(' '.join(map(str, args)))

Modified: pypy/dist/pypy/translator/cli/metavm.py
==============================================================================
--- pypy/dist/pypy/translator/cli/metavm.py	(original)
+++ pypy/dist/pypy/translator/cli/metavm.py	Fri May 19 22:44:24 2006
@@ -106,7 +106,6 @@
         generator.call_signature('object [pypylib]pypy.runtime.Utils::RuntimeNew(class [mscorlib]System.Type)')
         generator.cast_to(op.result.concretetype)
 
-
 PushAllArgs = _PushAllArgs()
 StoreResult = _StoreResult()
 Call = _Call()


From arigo at codespeak.net  Sat May 20 10:47:15 2006
From: arigo at codespeak.net (arigo at codespeak.net)
Date: Sat, 20 May 2006 10:47:15 +0200 (CEST)
Subject: [pypy-svn] r27492 - in pypy/dist/pypy/rpython: lltypesystem memory
	memory/test
Message-ID: <20060520084715.16BC610071@code0.codespeak.net>

Author: arigo
Date: Sat May 20 10:47:12 2006
New Revision: 27492

Modified:
   pypy/dist/pypy/rpython/lltypesystem/lloperation.py
   pypy/dist/pypy/rpython/memory/gc.py
   pypy/dist/pypy/rpython/memory/gctransform.py
   pypy/dist/pypy/rpython/memory/test/test_transformed_gc.py
Log:
Renamed 'malloced_lists' to 'pools'.  These pools are now GcOpaque
objects themselves, so that they are collectable.  Work in progress.
(Collecting a pool only means collecting the small overhead data, not
all the objects inside the pool, which stay alive as usual as long as
they are referenced.)



Modified: pypy/dist/pypy/rpython/lltypesystem/lloperation.py
==============================================================================
--- pypy/dist/pypy/rpython/lltypesystem/lloperation.py	(original)
+++ pypy/dist/pypy/rpython/lltypesystem/lloperation.py	Sat May 20 10:47:12 2006
@@ -319,7 +319,7 @@
     'gc_reload_possibly_moved': LLOp(),
     # experimental operations in support of thread cloning, only
     # implemented by the Mark&Sweep GC
-    'gc_x_swap_list':       LLOp(),
+    'gc_x_swap_pool':       LLOp(canraise=(MemoryError,)),
     'gc_x_clone':           LLOp(canraise=(MemoryError,)),
 
     # __________ stackless operation(s) __________

Modified: pypy/dist/pypy/rpython/memory/gc.py
==============================================================================
--- pypy/dist/pypy/rpython/memory/gc.py	(original)
+++ pypy/dist/pypy/rpython/memory/gc.py	Sat May 20 10:47:12 2006
@@ -12,8 +12,12 @@
 int_size = lltypesimulation.sizeof(lltype.Signed)
 gc_header_two_ints = 2*int_size
 
+X_POOL = lltype.GcOpaqueType('gc.pool')
+X_POOL_PTR = lltype.Ptr(X_POOL)
 X_CLONE = lltype.GcStruct('CloneData', ('gcobjectptr', llmemory.GCREF),
-                                       ('malloced_list', llmemory.Address))
+                                       ('pool',        X_POOL_PTR))
+X_CLONE_PTR = lltype.Ptr(X_CLONE)
+
 
 class GCError(Exception):
     pass
@@ -114,6 +118,9 @@
     HDR.become(lltype.Struct('header', ('typeid', lltype.Signed),
                                        ('next', HDRPTR)))
 
+    POOL = lltype.GcStruct('gc_pool')
+    POOLPTR = lltype.Ptr(POOL)
+
     def __init__(self, AddressLinkedList, start_heap_size=4096, get_roots=None):
         self.heap_usage = 0          # at the end of the latest collection
         self.bytes_malloced = 0      # since the latest collection
@@ -122,6 +129,7 @@
         self.AddressLinkedList = AddressLinkedList
         #self.set_query_functions(None, None, None, None, None, None, None)
         self.malloced_objects = lltype.nullptr(self.HDR)
+        self.curpool = lltype.nullptr(self.POOL)
         self.get_roots = get_roots
         self.gcheaderbuilder = GCHeaderBuilder(self.HDR)
 
@@ -255,8 +263,8 @@
             self.bytes_malloced_threshold = curr_heap_size
         end_time = time.time()
         self.total_collection_time += end_time - start_time
-        # warning, the following debug print allocates memory to manipulate
-        # the strings!  so it must be at the end
+        # warning, the following debug prints allocate memory to manipulate
+        # the strings!  so they must be at the end
         if DEBUG_PRINT:
             os.write(2, "  malloced since previous collection: %s bytes\n" %
                      old_malloced)
@@ -285,24 +293,54 @@
     init_gc_object_immortal = init_gc_object
 
     # experimental support for thread cloning
-    def x_swap_list(self, malloced_list):
-        # Swap the current malloced_objects linked list with another one.
-        # All malloc'ed objects are put into the current malloced_objects
-        # list; this is a way to separate objects depending on when they
-        # were allocated.
-        current = llmemory.cast_ptr_to_adr(self.malloced_objects)
-        self.malloced_objects = llmemory.cast_adr_to_ptr(malloced_list,
-                                                         self.HDRPTR)
-        return current
+    def x_swap_pool(self, newpool):
+        # Set newpool as the current pool (create one if newpool == NULL).
+        # All malloc'ed objects are put into the current pool;this is a
+        # way to separate objects depending on when they were allocated.
+        size_gc_header = self.gcheaderbuilder.size_gc_header
+        # invariant: each POOL GcStruct is at the _front_ of a linked list
+        # of malloced objects.
+        oldpool = self.curpool
+        if not oldpool:
+            # make a fresh pool object, which is automatically inserted at the
+            # front of the current list
+            oldpool = lltype.malloc(self.POOL)
+        else:
+            # manually insert oldpool at the front of the current list
+            addr = llmemory.cast_ptr_to_adr(oldpool)
+            addr -= size_gc_header
+            hdr = llmemory.cast_adr_to_ptr(addr, self.HDRPTR)
+            hdr.next = self.malloced_objects
+
+        newpool = lltype.cast_opaque_ptr(self.POOLPTR, newpool)
+        if newpool:
+            # newpool is at the front of the new linked list to install
+            addr = llmemory.cast_ptr_to_adr(newpool)
+            addr -= size_gc_header
+            hdr = llmemory.cast_adr_to_ptr(addr, self.HDRPTR)
+            self.malloced_objects = hdr.next
+        else:
+            # start a fresh new linked list
+            self.malloced_objects = lltype.nullptr(self.HDR)
+        # note that newpool will not be freed by a collect as long as
+        # it sits in self.malloced_objects_box, because it is not itself
+        # part of any linked list
+        self.curpool = newpool
+        return lltype.cast_opaque_ptr(X_POOL_PTR, oldpool)
 
     def x_clone(self, clonedata):
         # Recursively clone the gcobject and everything it points to,
         # directly or indirectly -- but stops at objects that are not
-        # in the malloced_list.  The gcobjectptr and the malloced_list
-        # fields of clonedata are adjusted to refer to the result.
+        # in the specified pool.  A new pool is built to contain the
+        # copies, and the 'gcobjectptr' and 'pool' fields of clonedata
+        # are adjusted to refer to the result.
         size_gc_header = self.gcheaderbuilder.size_gc_header
         oldobjects = self.AddressLinkedList()
-        hdr = llmemory.cast_adr_to_ptr(clonedata.malloced_list, self.HDRPTR)
+        oldpool = lltype.cast_opaque_ptr(self.POOLPTR, clonedata.pool)
+        addr = llmemory.cast_ptr_to_adr(oldpool)
+        addr -= size_gc_header
+        hdr = llmemory.cast_adr_to_ptr(addr, self.HDRPTR)
+        hdr = hdr.next
         while hdr:
             next = hdr.next
             hdr.typeid |= 1    # mark all objects from malloced_list
@@ -348,8 +386,6 @@
             newobj_addr = llmemory.cast_ptr_to_adr(newhdr) + size_gc_header
             gcptr_addr.address[0] = newobj_addr
 
-        clonedata.malloced_list = llmemory.cast_ptr_to_adr(newobjectlist)
-
         # re-create the original linked list
         next = lltype.nullptr(self.HDR)
         while oldobjects.non_empty():
@@ -359,6 +395,12 @@
             next = hdr
         oldobjects.delete()
 
+        # make the new pool object to collect newobjectlist
+        curpool = self.x_swap_pool(lltype.nullptr(X_POOL))
+        assert not self.malloced_objects
+        self.malloced_objects = newobjectlist
+        clonedata.pool = self.x_swap_pool(curpool)
+
 
 class SemiSpaceGC(GCBase):
     _alloc_flavor_ = "raw"

Modified: pypy/dist/pypy/rpython/memory/gctransform.py
==============================================================================
--- pypy/dist/pypy/rpython/memory/gctransform.py	(original)
+++ pypy/dist/pypy/rpython/memory/gctransform.py	Sat May 20 10:47:12 2006
@@ -844,9 +844,11 @@
         
         annhelper = annlowlevel.MixLevelHelperAnnotator(self.translator.rtyper)
 
-        def getfn(ll_function, args_s, s_result, inline=False):
+        def getfn(ll_function, args_s, s_result, inline=False,
+                  minimal_transform=True):
             graph = annhelper.getgraph(ll_function, args_s, s_result)
-            self.need_minimal_transform(graph)
+            if minimal_transform:
+                self.need_minimal_transform(graph)
             if inline:
                 self.graphs_to_inline[graph] = True
             return annhelper.graph2const(graph)
@@ -888,13 +890,18 @@
                                     [s_gc], annmodel.SomeTuple(statics_s))
 
         # experimental gc_x_* operations
-        self.x_swap_list_ptr = getfn(GCClass.x_swap_list.im_func,
-                                     [s_gc, annmodel.SomeAddress()],
-                                     annmodel.SomeAddress())
+        s_x_pool  = annmodel.SomePtr(gc.X_POOL_PTR)
+        s_x_clone = annmodel.SomePtr(gc.X_CLONE_PTR)
+        # the x_*() methods use some regular mallocs that must be
+        # transformed in the normal way
+        self.x_swap_pool_ptr = getfn(GCClass.x_swap_pool.im_func,
+                                     [s_gc, s_x_pool],
+                                     s_x_pool,
+                                     minimal_transform = False)
         self.x_clone_ptr = getfn(GCClass.x_clone.im_func,
-                                 [s_gc,
-                                  annmodel.SomePtr(lltype.Ptr(gc.X_CLONE))],
-                                 annmodel.s_None)
+                                 [s_gc, s_x_clone],
+                                 annmodel.s_None,
+                                 minimal_transform = False)
 
         annhelper.finish()   # at this point, annotate all mix-level helpers
         annhelper.backend_optimize()
@@ -1162,10 +1169,10 @@
                                         block.operations.index(op))
         return ops
 
-    def replace_gc_x_swap_list(self, op, livevars, block):
+    def replace_gc_x_swap_pool(self, op, livevars, block):
         [v_malloced] = op.args
         newop = SpaceOperation("direct_call",
-                               [self.x_swap_list_ptr, self.c_const_gc,
+                               [self.x_swap_pool_ptr, self.c_const_gc,
                                                       v_malloced],
                                op.result)
         return [newop]

Modified: pypy/dist/pypy/rpython/memory/test/test_transformed_gc.py
==============================================================================
--- pypy/dist/pypy/rpython/memory/test/test_transformed_gc.py	(original)
+++ pypy/dist/pypy/rpython/memory/test/test_transformed_gc.py	Sat May 20 10:47:12 2006
@@ -161,7 +161,7 @@
 from pypy.rpython.lltypesystem.lloperation import llop
 from pypy.rpython.lltypesystem import lltype
 from pypy.rpython.memory.support import INT_SIZE
-from pypy.rpython.memory.gc import X_CLONE
+from pypy.rpython.memory.gc import X_CLONE, X_POOL, X_POOL_PTR
 from pypy import conftest
 
 
@@ -304,18 +304,18 @@
             return a
         def func():
             a1 = make(111)
-            # start recording mallocs in a new list
-            oldlist = llop.gc_x_swap_list(llmemory.Address, llmemory.NULL)
+            # start recording mallocs in a new pool
+            oldpool = llop.gc_x_swap_pool(X_POOL_PTR, lltype.nullptr(X_POOL))
             # the following a2 goes into the new list
             a2 = make(222)
-            # now put the old list back and get the new list
-            newlist = llop.gc_x_swap_list(llmemory.Address, oldlist)
+            # now put the old pool back and get the new pool
+            newpool = llop.gc_x_swap_pool(X_POOL_PTR, oldpool)
             a3 = make(333)
             # clone a2
             a2ref = lltype.cast_opaque_ptr(llmemory.GCREF, a2)
             clonedata = lltype.malloc(X_CLONE)
             clonedata.gcobjectptr = a2ref
-            clonedata.malloced_list = newlist
+            clonedata.pool = newpool
             llop.gc_x_clone(lltype.Void, clonedata)
             a2copyref = clonedata.gcobjectptr
             a2copy = lltype.cast_opaque_ptr(lltype.Ptr(A), a2copyref)


From fijal at codespeak.net  Sat May 20 11:05:01 2006
From: fijal at codespeak.net (fijal at codespeak.net)
Date: Sat, 20 May 2006 11:05:01 +0200 (CEST)
Subject: [pypy-svn] r27493 - pypy/dist/pypy/translator/squeak/test
Message-ID: <20060520090501.1B86E10071@code0.codespeak.net>

Author: fijal
Date: Sat May 20 11:04:58 2006
New Revision: 27493

Modified:
   pypy/dist/pypy/translator/squeak/test/test_squeaktrans.py
Log:
Added failing test. I couldn't run it, but generated code is obviously wrong.


Modified: pypy/dist/pypy/translator/squeak/test/test_squeaktrans.py
==============================================================================
--- pypy/dist/pypy/translator/squeak/test/test_squeaktrans.py	(original)
+++ pypy/dist/pypy/translator/squeak/test/test_squeaktrans.py	Sat May 20 11:04:58 2006
@@ -4,6 +4,13 @@
 from pypy.translator.squeak.test.runtest import compile_function
 
 class TestGenSqueak:
+    def test_while(self):
+        def addon(i):
+            while not i == 1:
+                i -= 1
+            return i
+        fn = compile_function(addon, [int])
+        assert fn(4) == 1
 
     def test_theanswer(self):
         def theanswer():
@@ -34,7 +41,7 @@
             return A().m(i, j=3)
         fn = compile_function(simplemethod, [int])
         assert fn(1) == "6"
-
+    
     def test_nameclash_classes(self):
         from pypy.translator.squeak.test.support import A as A2
         class A:
@@ -177,7 +184,7 @@
         assert fn(-1) == "1"
         assert fn(0) == "0"
         assert fn(2) == "3"
-
+    
     def test_exceptreraise(self):
         def raising(i):
             if i == 0:


From ale at codespeak.net  Sat May 20 11:11:10 2006
From: ale at codespeak.net (ale at codespeak.net)
Date: Sat, 20 May 2006 11:11:10 +0200 (CEST)
Subject: [pypy-svn] r27494 - pypy/dist/pypy/lib/pyontology
Message-ID: <20060520091110.4EC1010071@code0.codespeak.net>

Author: ale
Date: Sat May 20 11:11:08 2006
New Revision: 27494

Modified:
   pypy/dist/pypy/lib/pyontology/pyontology.py
Log:
A small bug fix

Modified: pypy/dist/pypy/lib/pyontology/pyontology.py
==============================================================================
--- pypy/dist/pypy/lib/pyontology/pyontology.py	(original)
+++ pypy/dist/pypy/lib/pyontology/pyontology.py	Sat May 20 11:11:08 2006
@@ -385,6 +385,7 @@
         return Solver().solve(rep, verbose)
     
     def consistency(self, verbose=0):
+        self.check_TBoxes()
         self.rep = Repository(self.variables.keys(), self.variables, self.constraints)
         self.rep.consistency(verbose)
     
@@ -400,6 +401,7 @@
             while lis != rdf_nil:
                 res.append(list(self.graph.objects(lis, rdf_first))[0])
                 lis = list(self.graph.objects(lis, rdf_rest))[0]
+            self.variables[avar].setValues(res)
         else:
             # For testing
             avar = self.make_var(List, BNode('anon_%r'%rdf_list))
@@ -420,6 +422,7 @@
         if not var in builtin_voc :
             # var is not one of the builtin classes
             svar = self.make_var(self.variables[avar].__class__, s)
+            self.variables[avar].addValue(s)
         else:
             # var is a builtin class
             cls = builtin_voc[var]
@@ -433,7 +436,7 @@
             cls = self.variables[svar]
             if hasattr(cls, 'constraint'):
                 self.constraints.append(cls.constraint)
-        self.variables[avar].addValue(svar)
+        self.variables[avar].addValue(s)
     
     def first(self, s, var):
         pass
@@ -499,6 +502,7 @@
     
     def oneOf(self, s, var):
         var = self.flatten_rdf_list(var)
+        print "*******", var, type(var), self.variables[var]
         #avar = self.make_var(List, var)
         svar = self.make_var(ClassDomain, s)
         res = self.variables[var].getValues()
@@ -586,9 +590,9 @@
         cls_name = self.make_var(ClassDomain, cls)
         prop = self.variables[svar].property
         self.variables[svar].TBox[prop] = {'Cardinality': [( '<', int(var))]}
-#        formula = "not isinstance(%s[0], self.variables[%s]) or len(%s[1] < int(%s))" %(prop, cls_name, prop, var)
-#        constrain = Expression([prop], formula)
-#        self.constraints.append(constrain)
+        formula = "not isinstance(%s[0], self.variables[%s]) or len(%s[1]) < int(%s)" %(prop, cls_name, prop, var)
+        constrain = Expression([prop, cls_name, prop, var], formula)
+        self.constraints.append(constrain)
 
         for cls,vals in self.variables[prop].getValuesPrKey():
             if len(vals) < int(var):


From ale at codespeak.net  Sat May 20 11:21:21 2006
From: ale at codespeak.net (ale at codespeak.net)
Date: Sat, 20 May 2006 11:21:21 +0200 (CEST)
Subject: [pypy-svn] r27495 - pypy/dist/pypy/translator/microbench/pybench
Message-ID: <20060520092121.08AFF1006E@code0.codespeak.net>

Author: ale
Date: Sat May 20 11:21:19 2006
New Revision: 27495

Modified:
   pypy/dist/pypy/translator/microbench/pybench/pybench.py
Log:
A little toy for making Html reports of pybench benchmarks. There are some problems though. The benchmark results cant be pickled (because of pickling of sys.modules?), when using pypy-c. The sortable tables relies on Mochikit, which maybe should not be part of PyPy?

Modified: pypy/dist/pypy/translator/microbench/pybench/pybench.py
==============================================================================
--- pypy/dist/pypy/translator/microbench/pybench/pybench.py	(original)
+++ pypy/dist/pypy/translator/microbench/pybench/pybench.py	Sat May 20 11:21:19 2006
@@ -36,7 +36,8 @@
 # clock() values. You can use option -w to speedup the tests
 # by a fixed integer factor (the "warp factor").
 #
-
+import autopath
+from py.xml import html
 import sys,time,operator
 from CommandLine import *
 
@@ -262,40 +263,41 @@
 
     def html_stat(self, compare_to=None, hidenoise=0):
 
-        import autopath
-        from py.xml import html
 
         if not compare_to:
             table = html.table(
                         html.thead(
                             html.tr(
-                                [ html.th(x,  align='left', mochi_format = y)
+                                [ html.th(x, **{'mochi:format': y, 'align':'left'})
                             for (x,y) in [('Tests','str'), ('per run','float'),
                                   ('per oper.', 'float'), ('overhead', 'float')]])
                                     ),id = "sortable_table")
                                
             tests = self.tests.items()
             tests.sort()
+            tbody = html.tbody()
             for name,t in tests:
                 avg,op_avg,ov_avg = t.stat()
-                table.append(html.tr( html.td(name),
-                                      html.td((avg*1000.0),
+                tbody.append(html.tr( html.td(name),
+                                      html.td(avg*1000.0),
                                       html.td(op_avg*1000000.0),
-                                      html.td(ov_avg*1000.0))
+                                      html.td(ov_avg*1000.0)
                                     ))
-                table.append(html.tr(
+            table.append(tbody)
+            table.append(html.tr(
                                     'Average round time %s' % (self.roundtime * 1000.0))
                                             )
             return table
-        else:
+        elif isinstance(compare_to, Benchmark):
             table = html.table(html.thead(
-                      html.tr([ html.th(x,  align='left', mochi_format = y)
+                      html.tr([ html.th(x, **{'mochi:format': y, 'align':'left'})
                           for (x,y) in [('Tests','str'), ('per run','float'),
-                             ('per oper.', 'float'), ('diff', 'float')]]),
-                             id = "sortable_table"))
+                             ('per oper.', 'float'), ('diff', 'float')]])),
+                             id = "sortable_table", class_="datagrid")
             tests = self.tests.items()
             tests.sort()
             compatible = 1
+            tbody = html.tbody()
             for name,t in tests:
                 avg,op_avg,ov_avg = t.stat()
                 try:
@@ -313,11 +315,59 @@
                 else:
                     qavg,qop_avg = 'n/a', 'n/a'
                     compatible = 0
-                table.append(html.tr( html.td(name),
-                                      html.td((avg*1000.0),
+                tbody.append(html.tr( html.td(name),
+                                      html.td(avg*1000.0),
                                       html.td(op_avg*1000000.0),
                                       html.td(qop_avg)
-                                    )))
+                                    ))
+            if compatible and compare_to.roundtime > 0 and \
+               compare_to.version == self.version:
+                tbody.append(html.tr(
+                                 html.td('Average round time'),
+                                 html.td(self.roundtime * 1000.0),
+                                 html.td(''),
+                                 html.td('%+7.2f%%'% (((self.roundtime*self.warp)/ 
+                                        (compare_to.roundtime*compare_to.warp)-1.0)*100.0)
+                                        )))
+                                    
+            else:
+                tbody.append(html.tr(
+                                    html.td('Average round time'),
+                                    html.td(self.roundtime * 1000.0)))
+            table.append(tbody)
+            return table
+        else:
+            table = html.table(html.thead(
+                      html.tr([ html.th(x, **{'mochi:format': y, 'align':'left'})
+                          for (x,y) in [('Tests','str')]+[('pypy ver','float') for z in compare_to]
+                             ])),
+                             id = "sortable_table")
+            tests = self.tests.items()
+            tests.sort()
+            compatible = 1
+            for name,t in tests:
+                avg,op_avg,ov_avg = t.stat()
+                percent = []
+                for comp_to in compare_to:
+                    try:
+                        other = comp_to.tests[name]
+                    except KeyError:
+                        other = None
+                    if other and other.version == t.version and \
+                            other.operations == t.operations:
+                        avg1,op_avg1,ov_avg1 = other.stat()
+                        qop_avg = (op_avg/op_avg1-1.0)*100.0
+                        if hidenoise and abs(qop_avg) < 10:
+                            qop_avg = ''
+                        else:
+                            qop_avg = '%+7.2f%%' % qop_avg
+                    else:
+                        qavg,qop_avg = 'n/a', 'n/a'
+                        compatible = 0
+                    percent.append(qop_avg)
+                table.append(html.tr( html.td(name),
+                                      [html.td(qop_avg) for qop_avg in percent]
+                                    ))
             if compatible and compare_to.roundtime > 0 and \
                compare_to.version == self.version:
                 table.append(html.tr(
@@ -346,6 +396,31 @@
         buildno, buildate = platform.python_build()
         print '   Build:        %s (#%i)' % (buildate, buildno)
 
+class Document(object): 
+    
+    def __init__(self, title=None): 
+
+        self.body = html.body()
+        self.head = html.head()
+        self.doc = html.html(self.head, self.body)
+        if title is not None: 
+            self.head.append(
+                html.meta(name="title", content=title))
+        self.head.append(
+            html.link(rel="Stylesheet", type="text/css", href="MochiKit-1.1/examples/sortable_tables/sortable_tables.css"))
+        self.head.append(
+	            html.script(rel="JavaScript", type="text/javascript", src="MochiKit-1.1/lib/MochiKit/MochiKit.js"))
+        self.head.append(
+            html.script(rel="JavaScript", type="text/javascript", src="MochiKit-1.1/examples/sortable_tables/sortable_tables.js"))
+
+    def writetopath(self, p): 
+        assert p.ext == '.html'
+        self.head.append(
+            html.meta(name="Content-Type", content="text/html;charset=UTF-8")
+        )
+        s = self.doc.unicode().encode('utf-8')
+        p.write(s) 
+
 class PyBenchCmdline(Application):
 
     header = ("PYBENCH - a benchmark test suite for Python "
@@ -356,6 +431,7 @@
     options = [ArgumentOption('-n','number of rounds',Setup.Number_of_rounds),
                ArgumentOption('-f','save benchmark to file arg',''),
                ArgumentOption('-c','compare benchmark with the one in file arg',''),
+               ArgumentOption('-l','compare benchmark with the ones in the files arg',''),
                ArgumentOption('-s','show benchmark in file arg, then exit',''),
                ArgumentOption('-w','set warp factor to arg',Setup.Warp_factor),
                SwitchOption('-d','hide noise in compares', 0),
@@ -381,11 +457,12 @@
         reportfile = self.values['-f']
         show_bench = self.values['-s']
         compare_to = self.values['-c']
+        compare_to_many = self.values['-l']
         hidenoise = self.values['-d']
         warp = self.values['-w']
         nogc = self.values['--no-gc']
         html = self.values['-x']
-        
+
         # Switch off GC
         if nogc:
             try:
@@ -400,7 +477,7 @@
         print
 
         if not compare_to:
-            print_machine()
+            #print_machine()
             print
 
         if compare_to:
@@ -423,11 +500,15 @@
                 print 'Benchmark: %s (rounds=%i, warp=%i)' % \
                       (bench.name,bench.rounds,bench.warp)
                 print
+                print "*******************************************"
                 if html:
+                    print "Generating HTML"
+                    import py.path
+                    index = py.path.local('index.html')
                     table = bench.html_stat(compare_to, hidenoise)
-                    f = open('index.html','w')
-                    print >>f,table.unicode()
-                    f.close()
+                    doc = Document()
+                    doc.body.append(table)
+                    doc.writetopath(index)
                 else:
                     bench.print_stat(compare_to, hidenoise)
             except IOError:
@@ -456,6 +537,14 @@
             print
             return
         bench.print_stat(compare_to)
+        if html:
+            print "Generating HTML"
+            import py.path
+            index = py.path.local('index.html')
+            table = bench.html_stat(compare_to, hidenoise)
+            doc = Document()
+            doc.body.append(table)
+            doc.writetopath(index)
         # ring bell
         sys.stderr.write('\007')
 


From fijal at codespeak.net  Sat May 20 11:24:29 2006
From: fijal at codespeak.net (fijal at codespeak.net)
Date: Sat, 20 May 2006 11:24:29 +0200 (CEST)
Subject: [pypy-svn] r27496 - pypy/dist/pypy/translator/cli
Message-ID: <20060520092429.4899D10071@code0.codespeak.net>

Author: fijal
Date: Sat May 20 11:24:27 2006
New Revision: 27496

Modified:
   pypy/dist/pypy/translator/cli/gencli.py
Log:
Added temp name suffix parameter.


Modified: pypy/dist/pypy/translator/cli/gencli.py
==============================================================================
--- pypy/dist/pypy/translator/cli/gencli.py	(original)
+++ pypy/dist/pypy/translator/cli/gencli.py	Sat May 20 11:24:27 2006
@@ -25,7 +25,8 @@
                 outfile.close()
 
 class GenCli(object):
-    def __init__(self, tmpdir, translator, entrypoint = None , type_system_class = CTS , opcode_dict = opcodes ):
+    def __init__(self, tmpdir, translator, entrypoint = None, type_system_class = CTS, \
+        opcode_dict = opcodes, name_suffix = '.il' ):
         self.tmpdir = tmpdir
         self.translator = translator
         self.entrypoint = entrypoint
@@ -36,7 +37,7 @@
         else:
             self.assembly_name = entrypoint.get_name()
 
-        self.tmpfile = tmpdir.join(self.assembly_name + '.il')
+        self.tmpfile = tmpdir.join(self.assembly_name + name_suffix)
 
     def generate_source(self , asm_class = IlasmGenerator ):
         out = self.tmpfile.open('w')


From fijal at codespeak.net  Sat May 20 12:13:19 2006
From: fijal at codespeak.net (fijal at codespeak.net)
Date: Sat, 20 May 2006 12:13:19 +0200 (CEST)
Subject: [pypy-svn] r27497 - in pypy/dist/pypy/translator/js2: . test
Message-ID: <20060520101319.000A91006E@code0.codespeak.net>

Author: fijal
Date: Sat May 20 12:13:10 2006
New Revision: 27497

Added:
   pypy/dist/pypy/translator/js2/
   pypy/dist/pypy/translator/js2/__init__.py
   pypy/dist/pypy/translator/js2/asmgen.py
   pypy/dist/pypy/translator/js2/function.py
   pypy/dist/pypy/translator/js2/jts.py
   pypy/dist/pypy/translator/js2/log.py
   pypy/dist/pypy/translator/js2/opcodes.py
   pypy/dist/pypy/translator/js2/support.py
   pypy/dist/pypy/translator/js2/test/
   pypy/dist/pypy/translator/js2/test/__init__.py
   pypy/dist/pypy/translator/js2/test/browsertest.py
   pypy/dist/pypy/translator/js2/test/runtest.py
   pypy/dist/pypy/translator/js2/test/test_runtest.py
Log:
Added preliminary version of genjs with ootypesystem support. Supports basic if/while detection.


Added: pypy/dist/pypy/translator/js2/__init__.py
==============================================================================

Added: pypy/dist/pypy/translator/js2/asmgen.py
==============================================================================
--- (empty file)
+++ pypy/dist/pypy/translator/js2/asmgen.py	Sat May 20 12:13:10 2006
@@ -0,0 +1,153 @@
+
+""" backend generator routines
+"""
+
+from pypy.translator.js2.log import log
+
+from pypy.translator.squeak.node import LoopFinder
+
+from StringIO import StringIO
+
+class CodeGenerator(object):
+    def __init__(self, out, indentstep = 4, startblock = '{', endblock = '}'):
+        self._out = out
+        self._indent = 0
+        self._bol = True # begin of line
+        self._indentstep = indentstep
+        self._startblock = startblock
+        self._endblock = endblock
+    
+    def write(self, s, indent = 0):
+        indent = self._indent + (indent * self._indentstep)
+        
+        if self._bol:
+            self._out.write(' ' * indent)
+
+        self._out.write(s)
+        self._bol = (s and s[-1] == '\n')
+
+    def writeline(self, s=''):
+        self.write(s)
+        self.write('\n')
+
+    def openblock(self):
+        self.writeline(self._startblock)
+        self._indent += self._indentstep
+
+    def closeblock(self):
+        self._indent -= self._indentstep
+        self.writeline(self._endblock)
+
+class Queue ( object ):
+    def __init__ ( self , l , subst_table ):
+        self . l = l [:]
+        self . subst_table = subst_table
+    
+    def pop ( self ):
+        el = self . l . pop ()
+        return self . subst_table . get ( el , el )
+    
+    def __getattr__ ( self , attr ):
+        return getattr ( self . l , attr )
+    
+    def __len__ ( self ):
+        return len(self.l)
+
+class AsmGen ( object ):
+    """ JS 'assembler' generator routines
+    """
+    def __init__ ( self , outfile , name ):
+        self . outfile = outfile
+        self . name = name
+        self . subst_table = {}
+        self . right_hand = Queue ( [] , self . subst_table )
+        self . codegenerator = CodeGenerator ( outfile )
+    
+    def show_const ( self ):
+        return False
+
+    def begin_function ( self , name, arglist, returntype, is_entrypoint = False, *args ):
+        args = "," . join ( [ i [ 1 ] for i in arglist ] )
+        self . codegenerator . write ( "function %s (%s) " % ( name , args ) )
+        self . codegenerator . openblock ()
+    
+    def end_function ( self ):
+        self . codegenerator . closeblock ()
+    
+    def locals ( self , loc ):
+        self . codegenerator . writeline ( "var " + "," . join ( [ i [ 1 ] for i in loc ] ) + ";" )
+    
+    def load_arg ( self , v ):
+        self . right_hand . append ( v.name )
+    
+    def store_local ( self , v ):
+        name = self . subst_table . get ( v . name , v . name )
+        element = self . right_hand . pop ()
+        if element != name:
+            self . codegenerator . writeline ( "%s = %s;" % ( name , element ) )
+    
+    def load_local ( self , v ):
+        self . right_hand . append ( v . name )
+    
+    def load_const ( self , _type , v ):
+        self . right_hand . append ( str(v) )
+    
+    def ret ( self ):
+        self . codegenerator . writeline ( "return ( %s );" % self . right_hand . pop () )
+    
+    def begin_namespace ( self , namespace ):
+        pass
+    
+    def end_namespace ( self ):
+        pass
+    
+    def begin_class ( self , cl ):
+        pass
+    
+    def end_class ( self ):
+        pass
+
+    def emit ( self , opcode , *args ):
+        v1 = self . right_hand . pop ()
+        v2 = self . right_hand . pop ()
+        self . right_hand . append ( "(%s%s%s)" % ( v2 , opcode , v1 ) )
+
+    def call ( self , func ):
+        func_name,args = func
+        real_args = "," . join ( [ self . right_hand . pop () for i in xrange(len(args)) ] )
+        self . right_hand . append ( "%s ( %s )" % ( func_name , real_args ) )
+
+    def branch_if ( self , arg , exitcase ):
+        arg_name = self . subst_table . get ( arg . name , arg . name )
+        self . codegenerator . write ( "if ( %s == %s )" % ( arg_name , exitcase ) )
+        self . codegenerator . openblock ()
+    
+    def branch_while ( self , arg , exitcase ):
+        arg_name = self . subst_table . get ( arg . name , arg . name )
+        self . codegenerator . write ( "while ( %s == %s )" % ( arg_name , exitcase ) )
+        self . codegenerator . openblock ()
+    
+    def branch_else ( self ):
+        self . codegenerator . closeblock ()
+        self . codegenerator . write ( "else" )
+        self . codegenerator . openblock ()
+    
+    def close_branch ( self ):
+        self . codegenerator . closeblock ()
+
+    def label ( self , *args ):
+        self . codegenerator . openblock ()
+
+    def branch ( self , *args ):
+        #self . codegenerator . closeblock ()
+        pass
+    
+    def change_name ( self , from_name , to_name ):
+        self . subst_table [ from_name.name ] = to_name.name
+        #pass
+    
+    def cast_floor ( self ):
+        self . right_hand . append ( "Math.floor ( %s )" % self . right_hand . pop() )
+    
+    #def finish ( self ):
+    #    self . outfile . write ( "%r" % self . right_hand )

Added: pypy/dist/pypy/translator/js2/function.py
==============================================================================
--- (empty file)
+++ pypy/dist/pypy/translator/js2/function.py	Sat May 20 12:13:10 2006
@@ -0,0 +1,443 @@
+try:
+    set
+except NameError:
+    from sets import Set as set
+
+from pypy.objspace.flow import model as flowmodel
+from pypy.rpython.lltypesystem.lltype import Signed, Unsigned, Void, Bool, Float
+from pypy.rpython.lltypesystem.lltype import SignedLongLong, UnsignedLongLong
+from pypy.rpython.ootypesystem import ootype
+from pypy.translator.cli.option import getoption
+from pypy.translator.cli.cts import CTS
+from pypy.translator.cli.opcodes import opcodes
+from pypy.translator.cli.metavm import Generator,InstructionList
+from pypy.translator.cli.node import Node
+from pypy.translator.cli.class_ import Class
+
+from pypy.tool.ansi_print import ansi_log
+import py
+log = py.log.Producer("cli") 
+py.log.setconsumer("cli", ansi_log) 
+
+class LoopFinder:
+
+    def __init__(self, startblock):
+        self.loops = {}
+        self.parents = {startblock: startblock}
+        self.temps = {}
+        self.seen = set ()
+        self.block_seeing_order = {}
+        self.visit_Block(startblock)
+   
+    def visit_Block(self, block, switches=[]):
+        #self.temps.has_key()
+        self.seen.add(block)
+        self.block_seeing_order[block] = []
+        if block.exitswitch:
+            switches.append(block)
+            self.parents[block] = block
+        for link in block.exits:
+            self.block_seeing_order[block].append(link)
+            self.visit_Link(link, switches) 
+
+    def visit_Link(self, link, switches):
+        if link.target in switches:
+            if len(self.block_seeing_order[link.target]) == 1:
+                self.loops[link.target] = self.block_seeing_order[link.target][0].exitcase
+            else:
+                self.loops[link.target] = self.block_seeing_order[link.target][1].exitcase
+            
+        if not link.target in self.seen:
+            self.parents[link.target] = self.parents[link.prevblock]
+            self.visit_Block(link.target, switches)
+
+class Function(Node, Generator):
+    def __init__(self, db, graph, name = None, is_method = False, is_entrypoint = False ):
+        self.db = db
+        self.cts = db.type_system_class(db)
+        self.graph = graph
+        self.name = name or graph.name
+        self.is_method = is_method
+        self.is_entrypoint = is_entrypoint
+        self.blocknum = {}
+        self._set_args()
+        self._set_locals()
+
+    def get_name(self):
+        return self.name
+
+    def __hash__(self):
+        return hash(self.graph)
+
+    def __eq__(self, other):
+        return self.graph == other.graph
+
+    def _is_return_block(self, block):
+        return (not block.exits) and len(block.inputargs) == 1
+
+    def _is_raise_block(self, block):
+        return (not block.exits) and len(block.inputargs) == 2        
+
+    def render_block ( self , block ):
+        for op in block.operations:
+            self._render_op(op)
+    
+    def render_block ( self , block , stop_block = None ):
+        if block is stop_block:
+            return
+        
+        for op in block.operations:
+            self._render_op(op)
+        
+        if len ( block . exits ) == 0:
+            # return block
+            return_var = block.inputargs[0]
+            self . load ( return_var )
+            self . ilasm . ret ()
+        elif block . exitswitch is None:
+            # single exit block
+            assert ( len(block.exits) == 1 )
+            link = block . exits [ 0 ]
+            self . _setup_link ( link )
+            self . render_block ( link . target , stop_block )
+        elif block . exitswitch is flowmodel.c_last_exception:
+            raise NotImplementedError ( "Exception handling" )
+        else:
+            if self . loops . has_key ( block ):
+                # we've got loop
+                self . ilasm . branch_while ( block . exitswitch , self . loops [ block ] )
+                exit_case = block . exits [ self . loops [ block ] ]
+                self . _setup_link ( exit_case )
+                self . render_block ( exit_case . target , block )
+                for op in block . operations:
+                    self._render_op ( op )
+                self . ilasm . close_branch ()
+                exit_case = block . exits [ not self . loops [ block ] ]
+                self . _setup_link ( exit_case )
+                #log (  )
+                self . render_block ( exit_case . target , block )
+                #raise NotImplementedError ( "loop" )
+            else:
+                # just a simple if
+                assert ( len ( block . exits ) == 2 )
+                self . ilasm . branch_if ( block . exitswitch , True )
+                self . _setup_link ( block . exits [ True ] )
+                self . render_block ( block . exits [ True ] . target , stop_block )
+                self . ilasm . branch_else ()
+                self . _setup_link ( block . exits [ False ] )
+                self . render_block ( block . exits [ False ] . target , stop_block )
+                self . ilasm . close_branch ()
+
+    def render ( self , ilasm ):
+        if self . db . graph_name ( self . graph ) is not None and not self . is_method:
+            return # already rendered
+        
+        self . ilasm = ilasm
+        
+        self . loops = LoopFinder ( self . graph . startblock ) . loops
+        self . ilasm . begin_function ( self . name , self . args , None , None , None )
+
+        self . render_block ( self . graph . startblock )
+##            if self._is_return_block(block):
+##                return_blocks.append(block)
+##                continue
+##            
+##            for op in block.operations:
+##                self._render_op(op)
+##            
+##            for link in block.exits:
+##                target_label = self._get_block_name(link.target)
+##                if link.exitcase is None:
+##                    pass
+##                    self.ilasm.branch(target_label)
+##                else:
+##                    assert type(link.exitcase is bool)
+##                    assert block.exitswitch is not None
+##                    self.ilasm.branch_if( block.exitswitch, link.exitcase, target_label)
+##                self._setup_link(link)
+
+##        for block in return_blocks:
+##            return_var = block.inputargs[0]
+##            if return_var.concretetype is not Void:
+##                self.load(return_var)
+##            self.ilasm.ret()
+
+        self.ilasm.end_function()
+        if self.is_method:
+            pass # TODO
+        else:
+            self.db.record_function(self.graph, self.name)
+
+    def oldrender(self, ilasm):
+        if self.db.graph_name(self.graph) is not None and not self.is_method:
+            return # already rendered
+
+        loop_finder = LoopFinder ( self . graph . startblock )
+        # Work out it here
+
+        self.ilasm = ilasm
+        graph = self.graph
+        returntype, returnvar = self.cts.llvar_to_cts(graph.getreturnvar())
+
+        self.ilasm.begin_function(self.name, self.args, returntype, None , None )
+        self.ilasm.locals(self.locals)
+
+        return_blocks = []
+        for block in graph.iterblocks():
+            if self._is_return_block(block):
+                return_blocks.append(block)
+                continue
+                
+
+            #self.ilasm.label(self._get_block_name(block))
+
+            handle_exc = (block.exitswitch == flowmodel.c_last_exception)
+            if handle_exc:
+                self.ilasm.begin_try()
+
+            for op in block.operations:
+                #self._search_for_classes(op)
+                self._render_op(op)
+
+            if self._is_raise_block(block):
+                exc = block.inputargs[1]
+                self.load(exc)
+                self.ilasm.throw()
+
+            if handle_exc:
+                # search for the "default" block to be executed when no exception is raised
+                for link in block.exits:
+                    if link.exitcase is None:
+                        self._setup_link(link)
+                        target_label = self._get_block_name(link.target)
+                        self.ilasm.leave(target_label)
+                self.ilasm.end_try()
+
+                # catch the exception and dispatch to the appropriate block
+                for link in block.exits:
+                    if link.exitcase is None:
+                        continue # see above
+
+                    assert issubclass(link.exitcase, Exception)
+                    #cts_exc = self.cts.pyexception_to_cts(link.exitcase)
+                    #cts_exc = str(link.exitcase) # TODO: is it a bit hackish?
+                    ll_meta_exc = link.llexitcase
+                    self.db.record_const(ll_meta_exc)
+                    ll_exc = ll_meta_exc._inst.class_._INSTANCE
+                    cts_exc = self.cts.lltype_to_cts(ll_exc, False)
+                    self.ilasm.begin_catch(cts_exc)
+
+                    target = link.target
+                    if self._is_raise_block(target):
+                        # the exception value is on the stack, use it as the 2nd target arg
+                        assert len(link.args) == 2
+                        assert len(target.inputargs) == 2
+                        self.store(link.target.inputargs[1])
+                    else:
+                        # pop the unused exception value
+                        self.ilasm.pop()
+                        self._setup_link(link)
+                    
+                    target_label = self._get_block_name(target)
+                    self.ilasm.leave(target_label)
+                    self.ilasm.end_catch()
+
+            else:
+                # no exception handling, follow block links
+                for link in block.exits:
+                    target_label = self._get_block_name(link.target)
+                    if link.exitcase is None:
+                        pass
+                        #self.ilasm.branch(target_label)
+                    else:
+                        assert type(link.exitcase is bool)
+                        assert block.exitswitch is not None
+                        self.ilasm.branch_if( block.exitswitch, link.exitcase, target_label)
+                    self._setup_link(link)
+                    self.ilasm.close_branch()
+
+        # render return blocks at the end just to please the .NET
+        # runtime that seems to need a return statement at the end of
+        # the function
+        for block in return_blocks:
+            #self.ilasm.label(self._get_block_name(block))
+            return_var = block.inputargs[0]
+            if return_var.concretetype is not Void:
+                self.load(return_var)
+            self.ilasm.ret()
+
+        self.ilasm.end_function()
+        if self.is_method:
+            pass # TODO
+        else:
+            self.db.record_function(self.graph, self.name)
+
+    def _setup_link(self, link):
+        target = link.target
+        for to_load, to_store in zip(link.args, target.inputargs):
+            if to_load.concretetype is not Void:
+                self.load(to_load)
+                self.store(to_store)
+
+
+    def _set_locals(self):
+        # this code is partly borrowed from pypy.translator.c.funcgen.FunctionCodeGenerator
+        # TODO: refactoring to avoid code duplication
+
+        graph = self.graph
+        mix = [graph.getreturnvar()]
+        for block in graph.iterblocks():
+            self.blocknum[block] = len(self.blocknum)
+            mix.extend(block.inputargs)
+
+            for op in block.operations:
+                mix.extend(op.args)
+                mix.append(op.result)
+                if getattr(op, "cleanup", None) is not None:
+                    cleanup_finally, cleanup_except = op.cleanup
+                    for cleanupop in cleanup_finally + cleanup_except:
+                        mix.extend(cleanupop.args)
+                        mix.append(cleanupop.result)
+            for link in block.exits:
+                mix.extend(link.getextravars())
+                mix.extend(link.args)
+
+        # filter only locals variables, i.e.:
+        #  - must be variables
+        #  - must appear only once
+        #  - must not be function parameters
+        #  - must not have 'void' type
+
+        args = {}
+        for ctstype, name in self.args:
+            args[name] = True
+        
+        locals = []
+        seen = {}
+        for v in mix:
+            is_var = isinstance(v, flowmodel.Variable)
+            if id(v) not in seen and is_var and v.name not in args and v.concretetype is not Void:
+                locals.append(self.cts.llvar_to_cts(v))
+                seen[id(v)] = True
+
+        self.locals = locals
+
+    def _set_args(self):
+        args = [arg for arg in self.graph.getargs() if arg.concretetype is not Void]
+        self.args = map(self.cts.llvar_to_cts, args)
+        self.argset = set([argname for argtype, argname in self.args])
+
+    def _get_block_name(self, block):
+        return 'block%s' % self.blocknum[block]
+
+    def _search_for_classes(self, op):
+        for arg in op.args:
+            lltype = None
+            if isinstance(arg, flowmodel.Variable):
+                lltype = arg.concretetype
+            elif isinstance(arg, flowmodel.Constant):
+                lltype = arg.value
+
+            if isinstance(lltype, ootype._view) and isinstance(lltype._inst, ootype._instance):
+                lltype = lltype._inst._TYPE
+
+            if isinstance(lltype, ootype.Instance):
+                self.db.pending_class(lltype)
+
+    def _render_op(self, op):
+        # FIXME: what to do here?
+        instr_list = self.db.opcode_dict.get(op.opname, None)
+        if instr_list is not None:
+            #assert isinstance(instr_list, InstructionList)
+            instr_list.render(self, op)
+        else:
+            if getoption('nostop'):
+                log.WARNING('Unknown opcode: %s ' % op)
+                self.ilasm.opcode(str(op))
+            else:
+                assert False, 'Unknown opcode: %s ' % op
+
+    def field_name(self, obj, field):
+        class_, type_ = obj._lookup_field(field)
+        assert type_ is not None, 'Cannot find the field %s in the object %s' % (field, obj)
+        
+        class_name = self.class_name(class_)
+        field_type = self.cts.lltype_to_cts(type_)
+        return (field_type, class_name, field)
+
+    # following methods belongs to the Generator interface
+
+    def function_signature(self, graph):
+        return self.cts.graph_to_signature(graph, False)
+
+    def class_name(self, ooinstance):
+        return ooinstance._name
+
+    def emit(self, instr, *args):
+        self.ilasm.emit(instr, *args)
+
+    def call_graph(self, graph):
+        self.db.pending_function(graph)
+        func_sig = self.function_signature(graph)        
+        self.ilasm.call(func_sig)
+
+    def call_signature(self, signature):
+        self.ilasm.call(signature)
+
+    def cast_to(self, lltype):
+        cts_type = self.cts.lltype_to_cts(lltype, False)
+        self.ilasm.castclass(cts_type)
+        
+    def new(self, obj):
+        self.ilasm.new(self.cts.ctor_name(obj))
+
+    def set_field(self, obj, name):
+        self.ilasm.set_field(self.field_name(obj,name))
+
+    def get_field(self, obj, name):
+        self.ilasm.get_field(self.field_name(obj,name))
+        
+    def call_method(self, obj, name):
+        # TODO: use callvirt only when strictly necessary
+        signature, virtual = self.cts.method_signature(obj, name)
+        self.ilasm.call_method(signature, virtual)
+
+    def load(self, v):
+        if isinstance(v, flowmodel.Variable):
+            if v.name in self.argset:
+                selftype, selfname = self.args[0]
+                if self.is_method and v.name == selfname:
+                    self.ilasm.load_self()
+                else:
+                    self.ilasm.load_arg(v)
+            else:
+                self.ilasm.load_local(v)
+
+        elif isinstance(v, flowmodel.Constant):
+            self._load_const(v)
+        else:
+            assert False
+
+    def _load_const(self, const):        
+        type_ = const.concretetype
+        if type_ in [ Void , Bool , Float , Signed , Unsigned , SignedLongLong , UnsignedLongLong ]:
+            self.ilasm.load_const(type_,const.value)
+        else:
+            name = self.db.record_const(const.value)
+            cts_type = self.cts.lltype_to_cts(type_)
+            self.ilasm.load_set_field(cts_type,name)
+            #assert False, 'Unknown constant %s' % const
+
+    def store(self, v):
+        if isinstance(v, flowmodel.Variable):
+            if v.concretetype is not Void:
+                self.ilasm.store_local(v)
+        else:
+            assert False
+    
+    def change_name(self, name, to_name):
+        self.ilasm.change_name(name, to_name)
+    
+    def cast_floor(self):
+        self.ilasm.cast_floor()
+

Added: pypy/dist/pypy/translator/js2/jts.py
==============================================================================
--- (empty file)
+++ pypy/dist/pypy/translator/js2/jts.py	Sat May 20 12:13:10 2006
@@ -0,0 +1,52 @@
+
+""" JavaScript type system
+"""
+
+from pypy.rpython.ootypesystem import ootype
+
+class JTS ( object ):
+    """ Class implementing JavaScript type system
+    calls with mapping similiar to cts
+    """
+    def __init__ ( self , db ):
+        self . db = db
+    
+    def llvar_to_cts ( self , var ):
+        return 'var ',var.name
+    
+    def graph_to_signature(self, graph, is_method = False, func_name = None):
+        ret_type, ret_var = self.llvar_to_cts(graph.getreturnvar())
+        func_name = func_name or graph.name
+        
+        args = [arg for arg in graph.getargs() if arg.concretetype is not ootype.Void]
+        if is_method:
+            args = args[1:]
+
+        #arg_types = [self.lltype_to_cts(arg.concretetype) for arg in args]
+        #arg_list = ', '.join(arg_types)
+
+        return func_name,args
+    
+    def lltype_to_cts(self, t, include_class=True):
+        return 'var'
+##        if isinstance(t, ootype.Instance):
+##            self.db.pending_class(t)
+##            return self.__class(t._name, include_class)
+##        elif isinstance(t, ootype.Record):
+##            name = self.db.pending_record(t)
+##            return self.__class(name, include_class)
+##        elif isinstance(t, ootype.StaticMethod):
+##            return 'void' # TODO: is it correct to ignore StaticMethod?
+##        elif isinstance(t, ootype.List):
+##            item_type = self.lltype_to_cts(t._ITEMTYPE)
+##            return self.__class(PYPY_LIST % item_type, include_class)
+##        elif isinstance(t, ootype.Dict):
+##            key_type = self.lltype_to_cts(t._KEYTYPE)
+##            value_type = self.lltype_to_cts(t._VALUETYPE)
+##            return self.__class(PYPY_DICT % (key_type, value_type), include_class)
+##        elif isinstance(t, ootype.DictItemsIterator):
+##            key_type = self.lltype_to_cts(t._KEYTYPE)
+##            value_type = self.lltype_to_cts(t._VALUETYPE)
+##            return self.__class(PYPY_DICT_ITEMS_ITERATOR % (key_type, value_type), include_class)
+##
+##        return _get_from_dict(_lltype_to_cts, t, 'Unknown type %s' % t)

Added: pypy/dist/pypy/translator/js2/log.py
==============================================================================
--- (empty file)
+++ pypy/dist/pypy/translator/js2/log.py	Sat May 20 12:13:10 2006
@@ -0,0 +1,4 @@
+import py
+from pypy.tool.ansi_print import ansi_log
+log = py.log.Producer("js2")
+py.log.setconsumer("js2", ansi_log)

Added: pypy/dist/pypy/translator/js2/opcodes.py
==============================================================================
--- (empty file)
+++ pypy/dist/pypy/translator/js2/opcodes.py	Sat May 20 12:13:10 2006
@@ -0,0 +1,108 @@
+
+""" opcode definitions
+"""
+
+from pypy.translator.cli.metavm import PushArg, PushAllArgs, StoreResult,\
+     InstructionList, New, SetField, GetField, CallMethod, RuntimeNew, Call, MicroInstruction
+
+DoNothing = [PushAllArgs]
+
+class _SameAs ( MicroInstruction ):
+    def render ( self , generator , op ):
+        generator.change_name(op.result,op.args[0])
+        
+class _CastFloor ( MicroInstruction ):
+    def render ( self , generator , op ):
+        generator.cast_floor()
+
+CastFloor = [ PushAllArgs , _CastFloor() ]
+CopyName = [ PushAllArgs , _SameAs () ]
+SameAs = CopyName
+
+opcodes = {'int_mul': '*',
+    'int_add': '+',
+    'int_sub': '-',
+    'int_floordiv': '/',
+    'int_mod': '%',
+    'int_and': '&',
+    'int_or': '|',
+    'int_xor': '^',
+    'int_lshift': '<<',
+    'int_rshift': '>>',
+    'int_lt': '<',
+    'int_le': '<=',
+    'int_eq': '==',
+    'int_ne': '!=',
+    'int_ge': '>=',
+    'int_gt': '>',
+
+    'uint_mul': '*',
+    'uint_add': '+',
+    'uint_sub': '-',
+    'uint_floordiv': '/',
+    'uint_mod': '%',
+    'uint_and': '&',
+    'uint_or': '|',
+    'uint_xor': '^',
+    'uint_lshift': '<<',
+    'uint_rshift': '>>',
+    'uint_lt': '<',
+    'uint_le': '<=',
+    'uint_eq': '==',
+    'uint_ne': '!=',
+    'uint_ge': '>=',
+    'uint_gt': '>',
+
+    'unichar_lt': '<',
+    'unichar_le': '<=',
+    'unichar_eq': '==',
+    'unichar_ne': '!=',
+    'unichar_ge': '>=',
+    'unichar_gt': '>',
+
+    'float_mul': '*',
+    'float_add': '+',
+    'float_sub': '-',
+    'float_truediv': '/',
+    'float_mod': '%',
+    'float_lt': '<',
+    'float_le': '<=',
+    'float_eq': '==',
+    'float_ne': '!=',
+    'float_ge': '>=',
+    'float_gt': '>',
+
+    'ptr_eq': '==',
+    'ptr_ne': '!=',
+        
+    'direct_call' : [Call],
+    'same_as' : SameAs,
+    # when casting from bool we want that every truth value is casted
+    # to 1: we can't simply DoNothing, because the CLI stack could
+    # contains a truth value not equal to 1, so we should use the !=0
+    # trick.
+    'cast_bool_to_int':         CopyName,
+    'cast_bool_to_uint':        CopyName,
+    'cast_bool_to_float':       CopyName,
+    'cast_char_to_int':         CopyName,
+    'cast_unichar_to_int':      CopyName,
+    'cast_int_to_char':         CopyName,
+    'cast_int_to_unichar':      CopyName,
+    'cast_int_to_uint':         CopyName,
+    'cast_int_to_float':        CopyName,
+    'cast_int_to_longlong':     CopyName,
+    'cast_uint_to_int':         CopyName,
+    'cast_float_to_int':        CastFloor,
+    'cast_float_to_uint':       CastFloor,
+    'truncate_longlong_to_int': CopyName,
+}
+
+for key, value in opcodes.iteritems():
+    if type(value) is str:
+        value = InstructionList([PushAllArgs, value, StoreResult])
+    elif value is not None:
+        if StoreResult not in value:
+            value.append(StoreResult)
+        value = InstructionList(value)
+
+    opcodes[key] = value

Added: pypy/dist/pypy/translator/js2/support.py
==============================================================================
--- (empty file)
+++ pypy/dist/pypy/translator/js2/support.py	Sat May 20 12:13:10 2006
@@ -0,0 +1,61 @@
+from pypy.translator.gensupp import NameManager
+#from pypy.translator.js2.optimize import is_optimized_function
+
+class JavascriptNameManager(NameManager):
+    def __init__(self, js):
+        NameManager.__init__(self)
+        self.js = js
+        self.reserved = {}
+
+        #http://javascript.about.com/library/blreserved.htm
+        reserved_words = '''
+            abstract as boolean break byte case catch
+            char class continue const debugger default delete
+            do double else enum export extends false
+            final finally float for function goto if implements
+            import in instanceof int interface is long
+            namespace native new null package private protected
+            public return short static super switch synchronized
+            this throw throws transient true try typeof
+            use var void volatile while with
+            '''
+        for name in reserved_words.split():
+            self.reserved[name] = True
+
+        #http://javascript.about.com/library/blclassobj.htm
+        predefined_classes_and_objects = '''
+            Anchor anchors Applet applets Area Array Body
+            Button Checkbox Date document Error EvalError FileUpload
+            Form forms frame frames Function Hidden History
+            history Image images Link links location Math
+            MimeType mimetypes navigator Number Object Option options
+            Password Plugin plugins Radio RangeError ReferenceError RegExp
+            Reset screen Script Select String Style StyleSheet
+            Submit SyntaxError Text Textarea TypeError URIError window
+            '''
+        for name in predefined_classes_and_objects.split():
+            self.reserved[name] = True
+
+        #http://javascript.about.com/library/blglobal.htm
+        global_properties_and_methods = '''
+            _content closed Components controllers crypto defaultstatus directories
+            document frames history innerHeight innerWidth length location
+            locationbar menubar name navigator opener outerHeight outerWidth
+            pageXOffset pageYOffset parent personalbar pkcs11 prompter screen
+            screenX screenY scrollbars scrollX scrollY self statusbar
+            toolbar top window
+            '''
+        for name in global_properties_and_methods.split():
+            self.reserved[name] = True
+
+        self.make_reserved_names(' '.join(self.reserved))
+
+    def uniquename(self, name):
+        #if self.js.compress and name != self.js.functions[0].func_name and is_optimized_function(name) and name.startswith("ll_issubclass__object_vtablePtr_object_vtablePtr"):
+        #    name = 'f'
+        return NameManager.uniquename(self, name)
+
+    def ensure_non_reserved(self, name):
+        while name in self.reserved:
+            name += '_'
+        return name

Added: pypy/dist/pypy/translator/js2/test/__init__.py
==============================================================================

Added: pypy/dist/pypy/translator/js2/test/browsertest.py
==============================================================================
--- (empty file)
+++ pypy/dist/pypy/translator/js2/test/browsertest.py	Sat May 20 12:13:10 2006
@@ -0,0 +1,149 @@
+from BaseHTTPServer import HTTPServer, BaseHTTPRequestHandler
+import py
+from os   import system
+from cgi  import parse_qs
+from sys  import platform
+from time import sleep
+from webbrowser import open as webbrowser_open
+from pypy.translator.js2.log import log
+log = log.browsertest
+
+
+class config:
+    http_port = 10001
+
+    html_page = """
+
+
+
+
+    %(jsfilename)s
+    
+ +
+
+ +""" + + refresh_page = """ + + + + +
+// testcase: %(jstestcase)s
+%(jscode)s
+
+ +""" + + +class TestCase(object): + def __init__(self, jsfilename, jstestcase): + self.jsfilename = jsfilename + self.jscode = open(jsfilename).read() + self.jstestcase = jstestcase + self.result = None + + +class TestHandler(BaseHTTPRequestHandler): + """The HTTP handler class that provides the tests and handles results""" + + def do_GET(self): + global do_status + if self.path != "/test.html": + self.send_error(404, "File not found") + return + jsfilename = jstest.jsfilename + jstestcase = jstest.jstestcase + jscode = jstest.jscode + html_page = config.html_page % locals() + open("html_page.html", "w").write(html_page) + self.serve_data('text/html', html_page) + do_status = 'do_GET' + + def do_POST(self): + global do_status + if self.path != "/test.html": + self.send_error(404, "File not found") + return + form = parse_qs(self.rfile.read(int(self.headers['content-length']))) + jstest.result = form['result'][0] + + #we force a page refresh here because of two reason: + # 1. we don't have the next testcase ready yet + # 2. browser should ask again when we do have a test + jsfilename = jstest.jsfilename + jstestcase = jstest.jstestcase + jscode = jstest.jscode + refresh_page = config.refresh_page % locals() + self.serve_data('text/html', refresh_page) + do_status = 'do_POST' + + def serve_data(self, content_type, data): + self.send_response(200) + self.send_header("Content-type", content_type) + self.send_header("Content-length", len(data)) + self.end_headers() + self.wfile.write(data) + + +class BrowserTest(object): + """The browser driver""" + + def start_server(self, port): + server_address = ('', port) + self.httpd = HTTPServer(server_address, TestHandler) + + def get_result(self): + global do_status + do_status = None + while do_status != 'do_GET': + self.httpd.handle_request() + while do_status != 'do_POST': + self.httpd.handle_request() + return jstest.result + + +def jstest(jsfilename, jstestcase): + global driver, jstest + jstest = TestCase(str(jsfilename), str(jstestcase)) + + try: + driver + except: + driver = BrowserTest() + driver.start_server(config.http_port) + webbrowser_open('http://localhost:%d/test.html' % config.http_port) + + result = driver.get_result() + return result Added: pypy/dist/pypy/translator/js2/test/runtest.py ============================================================================== --- (empty file) +++ pypy/dist/pypy/translator/js2/test/runtest.py Sat May 20 12:13:10 2006 @@ -0,0 +1,81 @@ +''' + Skipped tests should still be fixed. (or only run with py.test --browser) + Sests with DONT in front of them will probably not be fixed for the time being. +''' + +import py, os +from pypy.translator.translator import TranslationContext +from pypy.translator.backendopt.all import backend_optimizations +from pypy.translator.js2.js import JS +from pypy.translator.js2.test.browsertest import jstest +from pypy.translator.js import conftest +from pypy.translator.js2.log import log +from pypy.conftest import option +log = log.runtest +use_browsertest = conftest.option.jsbrowser + +def _CLI_is_on_path(): + try: + py.path.local.sysfind('js') #we recommend Spidermonkey + except py.error.ENOENT: + return False + return True + +class compile_function(object): + def __init__(self, function, annotation, stackless=False, view=False): + if not use_browsertest and not _CLI_is_on_path(): + py.test.skip('Javascript CLI (js) not found') + + t = TranslationContext() + t.buildannotator().build_types(function, annotation) + + t.buildrtyper(type_system="ootype").specialize() + #print t.rtyper + + #backend_optimizations(t, raisingop2direct_call_all=True, inline_threshold=0, mallocs=False) + #backend_optimizations(t) + if view or option.view: + t.view() + #self.js = JS(t, [function, callback_function], stackless) + self.js = JS(t, [function], stackless) + self.js.write_source() + + def _conv(self, v): + if isinstance(v, str): + return "{hash:0, chars:'%s'}" % v + return str(v).lower() + + def __call__(self, *kwds): + args = ', '.join([self._conv(kw) for kw in kwds]) #lowerstr for (py)False->(js)false, etc. + + entry_function = self.js.translator.graphs[0].name + function_call = "%s(%s)" % (entry_function, args) + #if self.js.stackless: + # function_call = "slp_entry_point('%s')" % function_call + + if use_browsertest: + output = jstest(self.js.filename, function_call) + else: + cmd = 'echo "load(\'%s\'); print(%s)" | js 2>&1' % (self.js.filename, function_call) + log(cmd) + output = os.popen(cmd).read().strip() + for s in output.split('\n'): + log(s) + + if s == 'false': + res = False + elif s == 'true': + res = True + elif s == 'undefined': + res = None + elif s == 'inf': + res = 1e300 * 1e300 + elif s == 'NaN': + res = (1e300 * 1e300) / (1e300 * 1e300) + else: + log('javascript result:', s) + try: + res = eval(s) + except: + res = str(s) + return res Added: pypy/dist/pypy/translator/js2/test/test_runtest.py ============================================================================== --- (empty file) +++ pypy/dist/pypy/translator/js2/test/test_runtest.py Sat May 20 12:13:10 2006 @@ -0,0 +1,53 @@ +import py +from pypy.translator.js2.test.runtest import compile_function + +#test returntypes +##def test_bool_return(): +## def bool_return_False(): +## return False +## def bool_return_True(): +## return True +## f_false = compile_function(bool_return_False, []) +## assert f_false() == bool_return_False() +## f_true = compile_function(bool_return_True , []) +## assert f_true() == bool_return_True() +## +## +def test_int_return(): + def int_return(): + return 42 + f = compile_function(int_return, []) + assert f() == int_return() + +def test_float_return(): + def float_return(): + return 42.5 + f = compile_function(float_return, []) + assert f() == float_return() + +#test paramtypes +def test_bool_param(): + def bool_param(b): + return b + f = compile_function(bool_param, [bool]) + assert f(False) == bool_param(False) + assert f(True ) == bool_param(True ) + +def test_int_param(): + def int_param(n): + return n * 2 + f = compile_function(int_param, [int]) + assert f(42) == int_param(42) + +def test_float_param(): + def float_param(f): + return f * 3.0 + f = compile_function(float_param, [float]) + assert f(12.5) == float_param(12.5) + +def test_combined_params(): + def combined_params(b, n, f): + return int(int(b) * 5 + n * 2 + f * 3.0) + f = compile_function(combined_params, [bool,int,float]) + assert f(False, 13, 12.5) == combined_params(False, 13, 12.5) + assert f(True , 13, 12.5) == combined_params(True , 13, 12.5) From arigo at codespeak.net Sat May 20 13:00:40 2006 From: arigo at codespeak.net (arigo at codespeak.net) Date: Sat, 20 May 2006 13:00:40 +0200 (CEST) Subject: [pypy-svn] r27498 - pypy/dist/pypy/translator Message-ID: <20060520110040.3FE791006E@code0.codespeak.net> Author: arigo Date: Sat May 20 13:00:38 2006 New Revision: 27498 Modified: pypy/dist/pypy/translator/interactive.py Log: Don't silently ignore unknown options Modified: pypy/dist/pypy/translator/interactive.py ============================================================================== --- pypy/dist/pypy/translator/interactive.py (original) +++ pypy/dist/pypy/translator/interactive.py Sat May 20 13:00:38 2006 @@ -105,6 +105,8 @@ if getattr(self.driver.options, optname) != value: raise Exception("inconsistent option supplied: %s" % optname) else: + if not hasattr(self.driver.options, optname): + raise TypeError('driver has no option %r' % (optname,)) setattr(self.driver.options, optname, value) self.frozen_options[optname] = True From arigo at codespeak.net Sat May 20 13:06:52 2006 From: arigo at codespeak.net (arigo at codespeak.net) Date: Sat, 20 May 2006 13:06:52 +0200 (CEST) Subject: [pypy-svn] r27499 - pypy/dist/pypy/translator Message-ID: <20060520110652.911971006E@code0.codespeak.net> Author: arigo Date: Sat May 20 13:06:51 2006 New Revision: 27499 Modified: pypy/dist/pypy/translator/interactive.py Log: Grumble, more fixing. Modified: pypy/dist/pypy/translator/interactive.py ============================================================================== --- pypy/dist/pypy/translator/interactive.py (original) +++ pypy/dist/pypy/translator/interactive.py Sat May 20 13:06:51 2006 @@ -101,6 +101,8 @@ self.ensure_setup(argtypes, kwds.get('policy'), kwds.get('standalone')) for optname, value in kwds.iteritems(): + if optname in ('policy', 'standalone'): + continue if optname in self.frozen_options: if getattr(self.driver.options, optname) != value: raise Exception("inconsistent option supplied: %s" % optname) From cfbolz at codespeak.net Sat May 20 14:47:33 2006 From: cfbolz at codespeak.net (cfbolz at codespeak.net) Date: Sat, 20 May 2006 14:47:33 +0200 (CEST) Subject: [pypy-svn] r27504 - pypy/dist/pypy/doc Message-ID: <20060520124733.1446510070@code0.codespeak.net> Author: cfbolz Date: Sat May 20 14:47:31 2006 New Revision: 27504 Modified: pypy/dist/pypy/doc/coding-guide.txt Log: finally add a link to PEP 8 to the coding guide Modified: pypy/dist/pypy/doc/coding-guide.txt ============================================================================== --- pypy/dist/pypy/doc/coding-guide.txt (original) +++ pypy/dist/pypy/doc/coding-guide.txt Sat May 20 14:47:31 2006 @@ -8,7 +8,11 @@ This document describes coding requirements and conventions for working with the PyPy code base. Please read it carefully and -ask back any questions you might have. +ask back any questions you might have. The document does not talk +very much about coding style issues. We mostly follow `PEP 8`_ though. +If in doubt, follow the style that is already present in the code base. + +.. _`PEP 8`: http://www.python.org/dev/peps/pep-0008/ .. _`RPython`: From mwh at codespeak.net Sat May 20 15:00:32 2006 From: mwh at codespeak.net (mwh at codespeak.net) Date: Sat, 20 May 2006 15:00:32 +0200 (CEST) Subject: [pypy-svn] r27505 - pypy/dist/pypy/rpython/memory Message-ID: <20060520130032.6984C10070@code0.codespeak.net> Author: mwh Date: Sat May 20 15:00:30 2006 New Revision: 27505 Modified: pypy/dist/pypy/rpython/memory/gctransform.py Log: allow the stacklessgctransformer to annotate additional helpers. Modified: pypy/dist/pypy/rpython/memory/gctransform.py ============================================================================== --- pypy/dist/pypy/rpython/memory/gctransform.py (original) +++ pypy/dist/pypy/rpython/memory/gctransform.py Sat May 20 15:00:30 2006 @@ -903,6 +903,8 @@ annmodel.s_None, minimal_transform = False) + self.annotate_more_helpers(annhelper) + annhelper.finish() # at this point, annotate all mix-level helpers annhelper.backend_optimize() @@ -919,6 +921,9 @@ FLDTYPE = getattr(HDR, fldname) fields.append((fldname, FLDTYPE)) + def annotate_more_helpers(self, annhelper): + pass + def build_stack_root_iterator(self): gcdata = self.gcdata sizeofaddr = llmemory.sizeof(llmemory.Address) @@ -1271,6 +1276,9 @@ # nothing left to inline during code generation self.inline = False + def annotate_more_helpers(self, annhelper): + pass + def replace_and_inline_malloc_already_now(self): for graph in self.translator.graphs: any_malloc = False From arigo at codespeak.net Sat May 20 15:26:21 2006 From: arigo at codespeak.net (arigo at codespeak.net) Date: Sat, 20 May 2006 15:26:21 +0200 (CEST) Subject: [pypy-svn] r27506 - in pypy/dist/pypy/rpython/memory: . test Message-ID: <20060520132621.D22C710070@code0.codespeak.net> Author: arigo Date: Sat May 20 15:26:20 2006 New Revision: 27506 Modified: pypy/dist/pypy/rpython/memory/gc.py pypy/dist/pypy/rpython/memory/test/test_transformed_gc.py Log: Intermediate check-in to show the structure of the linked lists used by x_clone(). The test fails in obscure heap-corruption-like ways, but I hope it is "just" a matter of bug fixes in x_clone() or x_swap_list(). Modified: pypy/dist/pypy/rpython/memory/gc.py ============================================================================== --- pypy/dist/pypy/rpython/memory/gc.py (original) +++ pypy/dist/pypy/rpython/memory/gc.py Sat May 20 15:26:20 2006 @@ -121,6 +121,11 @@ POOL = lltype.GcStruct('gc_pool') POOLPTR = lltype.Ptr(POOL) + POOLNODE = lltype.ForwardReference() + POOLNODEPTR = lltype.Ptr(POOLNODE) + POOLNODE.become(lltype.Struct('gc_pool_node', ('linkedlist', HDRPTR), + ('nextnode', POOLNODEPTR))) + def __init__(self, AddressLinkedList, start_heap_size=4096, get_roots=None): self.heap_usage = 0 # at the end of the latest collection self.bytes_malloced = 0 # since the latest collection @@ -129,9 +134,22 @@ self.AddressLinkedList = AddressLinkedList #self.set_query_functions(None, None, None, None, None, None, None) self.malloced_objects = lltype.nullptr(self.HDR) - self.curpool = lltype.nullptr(self.POOL) self.get_roots = get_roots self.gcheaderbuilder = GCHeaderBuilder(self.HDR) + # pools, for x_swap_pool(): + # 'curpool' is the current pool, lazily allocated (i.e. NULL means + # the current POOL object is not yet malloc'ed). POOL objects are + # usually at the start of a linked list of objects, via the HDRs. + # The exception is 'curpool' whose linked list of objects is in + # 'self.malloced_objects' instead of in the header of 'curpool'. + # POOL objects are never in the middle of a linked list themselves. + self.curpool = lltype.nullptr(self.POOL) + # 'poolnodes' is a linked list of all such linked lists. Each + # linked list will usually start with a POOL object, but it can + # also contain only normal objects if the POOL object at the head + # was already freed. The objects in 'malloced_objects' are not + # found via 'poolnodes'. + self.poolnodes = lltype.nullptr(self.POOLNODE) def malloc(self, typeid, length=0): size = self.fixed_size(typeid) @@ -235,30 +253,53 @@ i += 1 hdr.typeid = hdr.typeid | 1 objects.delete() - newmo = self.AddressLinkedList() + # also mark self.curpool + if self.curpool: + gc_info = llmemory.cast_ptr_to_adr(self.curpool) - size_gc_header + hdr = llmemory.cast_adr_to_ptr(gc_info, self.HDRPTR) + hdr.typeid = hdr.typeid | 1 + curr_heap_size = 0 freed_size = 0 - hdr = self.malloced_objects - newmo = lltype.nullptr(self.HDR) - while hdr: #sweep - typeid = hdr.typeid >> 1 - next = hdr.next - addr = llmemory.cast_ptr_to_adr(hdr) - size = self.fixed_size(typeid) - if self.is_varsize(typeid): - length = (addr + size_gc_header + self.varsize_offset_to_length(typeid)).signed[0] - size += self.varsize_item_sizes(typeid) * length - estimate = raw_malloc_usage(size_gc_header + size) - if hdr.typeid & 1: - hdr.typeid = hdr.typeid & (~1) - hdr.next = newmo - newmo = hdr - curr_heap_size += estimate + firstpoolnode = lltype.malloc(self.POOLNODE, flavor='raw') + firstpoolnode.linkedlist = self.malloced_objects + firstpoolnode.nextnode = self.poolnodes + prevpoolnode = lltype.nullptr(self.POOLNODE) + poolnode = firstpoolnode + while poolnode: #sweep + ppnext = lltype.direct_fieldptr(poolnode, 'linkedlist') + hdr = poolnode.linkedlist + while hdr: #sweep + typeid = hdr.typeid >> 1 + next = hdr.next + addr = llmemory.cast_ptr_to_adr(hdr) + size = self.fixed_size(typeid) + if self.is_varsize(typeid): + length = (addr + size_gc_header + self.varsize_offset_to_length(typeid)).signed[0] + size += self.varsize_item_sizes(typeid) * length + estimate = raw_malloc_usage(size_gc_header + size) + if hdr.typeid & 1: + hdr.typeid = hdr.typeid & (~1) + ppnext[0] = hdr + ppnext = lltype.direct_fieldptr(hdr, 'next') + curr_heap_size += estimate + else: + freed_size += estimate + raw_free(addr) + hdr = next + ppnext[0] = lltype.nullptr(self.HDR) + next = poolnode.nextnode + if not poolnode.linkedlist and prevpoolnode: + # completely empty node + prevpoolnode.nextnode = next + lltype.free(poolnode, flavor='raw') else: - freed_size += estimate - raw_free(addr) - hdr = next - self.malloced_objects = newmo + prevpoolnode = poolnode + poolnode = next + self.malloced_objects = firstpoolnode.linkedlist + self.poolnodes = firstpoolnode.nextnode + lltype.free(firstpoolnode, flavor='raw') + if curr_heap_size > self.bytes_malloced_threshold: self.bytes_malloced_threshold = curr_heap_size end_time = time.time() @@ -305,6 +346,14 @@ # make a fresh pool object, which is automatically inserted at the # front of the current list oldpool = lltype.malloc(self.POOL) + addr = llmemory.cast_ptr_to_adr(oldpool) + addr -= size_gc_header + hdr = llmemory.cast_adr_to_ptr(addr, self.HDRPTR) + # put this new POOL object in the poolnodes list + node = lltype.malloc(self.POOLNODE, flavor="raw") + node.linkedlist = hdr + node.nextnode = self.poolnodes + self.poolnodes = node else: # manually insert oldpool at the front of the current list addr = llmemory.cast_ptr_to_adr(oldpool) @@ -319,12 +368,13 @@ addr -= size_gc_header hdr = llmemory.cast_adr_to_ptr(addr, self.HDRPTR) self.malloced_objects = hdr.next + # invariant: now that objects in the hdr.next list are accessible + # through self.malloced_objects, make sure they are not accessible + # via poolnodes (which has a node pointing to newpool): + hdr.next = lltype.nullptr(self.HDR) else: # start a fresh new linked list self.malloced_objects = lltype.nullptr(self.HDR) - # note that newpool will not be freed by a collect as long as - # it sits in self.malloced_objects_box, because it is not itself - # part of any linked list self.curpool = newpool return lltype.cast_opaque_ptr(X_POOL_PTR, oldpool) @@ -334,13 +384,19 @@ # in the specified pool. A new pool is built to contain the # copies, and the 'gcobjectptr' and 'pool' fields of clonedata # are adjusted to refer to the result. + + # install a new pool into which all the mallocs go + curpool = self.x_swap_pool(lltype.nullptr(X_POOL)) + size_gc_header = self.gcheaderbuilder.size_gc_header oldobjects = self.AddressLinkedList() - oldpool = lltype.cast_opaque_ptr(self.POOLPTR, clonedata.pool) + # if no pool specified, use the current pool as the 'source' pool + oldpool = clonedata.pool or curpool + oldpool = lltype.cast_opaque_ptr(self.POOLPTR, oldpool) addr = llmemory.cast_ptr_to_adr(oldpool) addr -= size_gc_header hdr = llmemory.cast_adr_to_ptr(addr, self.HDRPTR) - hdr = hdr.next + hdr = hdr.next # skip the POOL object itself while hdr: next = hdr.next hdr.typeid |= 1 # mark all objects from malloced_list @@ -353,10 +409,11 @@ stack = self.AddressLinkedList() stack.append(llmemory.cast_ptr_to_adr(clonedata) + llmemory.offsetof(X_CLONE, 'gcobjectptr')) - newobjectlist = lltype.nullptr(self.HDR) while stack.non_empty(): gcptr_addr = stack.pop() oldobj_addr = gcptr_addr.address[0] + if not oldobj_addr: + continue # pointer is NULL oldhdr = llmemory.cast_adr_to_ptr(oldobj_addr - size_gc_header, self.HDRPTR) typeid = oldhdr.typeid @@ -369,12 +426,11 @@ raise NotImplementedError else: size = self.fixed_size(typeid) - newmem = raw_malloc(size_gc_header + size) - newhdr = llmemory.cast_adr_to_ptr(newmem, self.HDRPTR) - newhdr.typeid = typeid << 1 - newhdr.next = newobjectlist - newobjectlist = newhdr - newobj_addr = newmem + size_gc_header + # XXX! collect() at the beginning if the free heap is low + newobj = self.malloc_fixedsize(typeid, size, False) + newobj_addr = llmemory.cast_ptr_to_adr(newobj) + newhdr_addr = newobj_addr - size_gc_header + newhdr = llmemory.cast_adr_to_ptr(newhdr_addr, self.HDRPTR) raw_memcopy(oldobj_addr, newobj_addr, size) offsets = self.offsets_to_gc_pointers(typeid) i = 0 @@ -395,10 +451,8 @@ next = hdr oldobjects.delete() - # make the new pool object to collect newobjectlist - curpool = self.x_swap_pool(lltype.nullptr(X_POOL)) - assert not self.malloced_objects - self.malloced_objects = newobjectlist + # build the new pool object collecting the new objects, and + # reinstall the pool that was current at the beginning of x_clone() clonedata.pool = self.x_swap_pool(curpool) Modified: pypy/dist/pypy/rpython/memory/test/test_transformed_gc.py ============================================================================== --- pypy/dist/pypy/rpython/memory/test/test_transformed_gc.py (original) +++ pypy/dist/pypy/rpython/memory/test/test_transformed_gc.py Sat May 20 15:26:20 2006 @@ -295,7 +295,8 @@ def test_cloning(self): B = lltype.GcStruct('B', ('x', lltype.Signed)) - A = lltype.GcStruct('A', ('b', lltype.Ptr(B))) + A = lltype.GcStruct('A', ('b', lltype.Ptr(B)), + ('unused', lltype.Ptr(B))) def make(n): b = lltype.malloc(B) b.x = n @@ -333,6 +334,85 @@ class transformerclass(gctransform.StacklessFrameworkGCTransformer): GC_PARAMS = {'start_heap_size': 4096 } + def test_tree_cloning(self): + py.test.skip("aaaaaaaaaaaaaaaaaaaaaaargh later") + import os + # this makes a tree of calls. Each leaf stores its path (a linked + # list) in 'result'. Paths are mutated in-place but the leaves don't + # see each other's mutations because of x_clone. + NODE = lltype.GcForwardReference() + NODE.become(lltype.GcStruct('node', ('index', lltype.Signed), + ('counter', lltype.Signed), + ('next', lltype.Ptr(NODE)))) + PATHARRAY = lltype.GcArray(lltype.Ptr(NODE)) + clonedata = lltype.malloc(X_CLONE) + + def clone(node): + # that's for testing if the test is correct... + if not node: + return node + newnode = lltype.malloc(NODE) + newnode.index = node.index + newnode.counter = node.counter + newnode.next = clone(node.next) + return newnode + + def do_call(result, path, index, remaining_depth): + # clone the while path + clonedata.gcobjectptr = lltype.cast_opaque_ptr(llmemory.GCREF, + path) + clonedata.pool = lltype.nullptr(X_POOL) + llop.gc_x_clone(lltype.Void, clonedata) + # install the new pool as the current one + parentpool = llop.gc_x_swap_pool(X_POOL_PTR, clonedata.pool) + path = lltype.cast_opaque_ptr(lltype.Ptr(NODE), + clonedata.gcobjectptr) + + # The above should have the same effect as: + # path = clone(path) + + # bump all the path's counters by one + p = path + while p: + p.counter += 1 + p = p.next + + if remaining_depth == 0: + result[index] = path # leaf + else: + node = lltype.malloc(NODE) + node.index = index * 2 + node.counter = 0 + node.next = path + do_call(result, node, node.index, remaining_depth - 1) + node.index += 1 # mutation! + do_call(result, node, node.index, remaining_depth - 1) + + # restore the parent pool + llop.gc_x_swap_pool(X_POOL_PTR, parentpool) + + def check(path, index, level, depth): + if level == depth: + assert index == 0 + assert not path + else: + assert path.index == index + assert path.counter == level + 1 + check(path.next, index >> 1, level + 1, depth) + + def func(depth, dummy): + result = lltype.malloc(PATHARRAY, 1 << depth) + os.write(2, 'building tree... ') + do_call(result, lltype.nullptr(NODE), 0, depth) + os.write(2, 'checking tree... ') + for i in range(1 << depth): + check(result[i], i, 0, depth) + os.write(2, 'ok\n') + return 1 + run = self.runner(func, nbargs=2) + res = run([5, 0]) + assert res == 1 + class TestSemiSpaceGC(TestMarkSweepGC): def setup_class(cls): From mwh at codespeak.net Sat May 20 15:57:15 2006 From: mwh at codespeak.net (mwh at codespeak.net) Date: Sat, 20 May 2006 15:57:15 +0200 (CEST) Subject: [pypy-svn] r27507 - in pypy/dist/pypy/rpython: lltypesystem memory memory/test Message-ID: <20060520135715.6E04310070@code0.codespeak.net> Author: mwh Date: Sat May 20 15:57:12 2006 New Revision: 27507 Modified: pypy/dist/pypy/rpython/lltypesystem/lloperation.py pypy/dist/pypy/rpython/memory/gc.py pypy/dist/pypy/rpython/memory/gctransform.py pypy/dist/pypy/rpython/memory/test/test_transformed_gc.py Log: the boring bits of the x_become operation, no actual implementation yet. Modified: pypy/dist/pypy/rpython/lltypesystem/lloperation.py ============================================================================== --- pypy/dist/pypy/rpython/lltypesystem/lloperation.py (original) +++ pypy/dist/pypy/rpython/lltypesystem/lloperation.py Sat May 20 15:57:12 2006 @@ -321,6 +321,11 @@ # implemented by the Mark&Sweep GC 'gc_x_swap_pool': LLOp(canraise=(MemoryError,)), 'gc_x_clone': LLOp(canraise=(MemoryError,)), + # this one is even more experimental; only implemented with the + # Mark&Sweep GC, and likely only useful when combined with + # stackless: + 'gc_x_become': LLOp(canraise=(RuntimeError,)), + # __________ stackless operation(s) __________ Modified: pypy/dist/pypy/rpython/memory/gc.py ============================================================================== --- pypy/dist/pypy/rpython/memory/gc.py (original) +++ pypy/dist/pypy/rpython/memory/gc.py Sat May 20 15:57:12 2006 @@ -455,6 +455,8 @@ # reinstall the pool that was current at the beginning of x_clone() clonedata.pool = self.x_swap_pool(curpool) + def x_become(self, target_addr, source_addr): + pass class SemiSpaceGC(GCBase): _alloc_flavor_ = "raw" Modified: pypy/dist/pypy/rpython/memory/gctransform.py ============================================================================== --- pypy/dist/pypy/rpython/memory/gctransform.py (original) +++ pypy/dist/pypy/rpython/memory/gctransform.py Sat May 20 15:57:12 2006 @@ -903,7 +903,11 @@ annmodel.s_None, minimal_transform = False) - self.annotate_more_helpers(annhelper) + self.x_become_ptr = getfn( + GCClass.x_become.im_func, + [s_gc, annmodel.SomeAddress(), annmodel.SomeAddress()], + annmodel.s_None, + minimal_transform = False) annhelper.finish() # at this point, annotate all mix-level helpers annhelper.backend_optimize() @@ -921,9 +925,6 @@ FLDTYPE = getattr(HDR, fldname) fields.append((fldname, FLDTYPE)) - def annotate_more_helpers(self, annhelper): - pass - def build_stack_root_iterator(self): gcdata = self.gcdata sizeofaddr = llmemory.sizeof(llmemory.Address) @@ -1190,6 +1191,14 @@ op.result) return [newop] + def replace_gc_x_become(self, op, livevars, block): + [v_target, v_source] = op.args + newop = SpaceOperation("direct_call", + [self.x_become_ptr, self.c_const_gc, + v_target, v_source], + op.result) + return [newop] + def push_alive_nopyobj(self, var): return [] @@ -1276,9 +1285,6 @@ # nothing left to inline during code generation self.inline = False - def annotate_more_helpers(self, annhelper): - pass - def replace_and_inline_malloc_already_now(self): for graph in self.translator.graphs: any_malloc = False Modified: pypy/dist/pypy/rpython/memory/test/test_transformed_gc.py ============================================================================== --- pypy/dist/pypy/rpython/memory/test/test_transformed_gc.py (original) +++ pypy/dist/pypy/rpython/memory/test/test_transformed_gc.py Sat May 20 15:57:12 2006 @@ -334,6 +334,23 @@ class transformerclass(gctransform.StacklessFrameworkGCTransformer): GC_PARAMS = {'start_heap_size': 4096 } + def test_x_become(self): + S = lltype.GcStruct("S", ('x', lltype.Signed)) + def f(): + x = lltype.malloc(S) + x.x = 10 + y = lltype.malloc(S) + y.x = 20 + z = x + llop.gc_x_become(lltype.Void, + llmemory.cast_ptr_to_adr(x), + llmemory.cast_ptr_to_adr(y)) + return z.x + run = self.runner(f) + res = run([]) + # not implemented yet! + #assert res == 20 + def test_tree_cloning(self): py.test.skip("aaaaaaaaaaaaaaaaaaaaaaargh later") import os From mwh at codespeak.net Sat May 20 16:37:29 2006 From: mwh at codespeak.net (mwh at codespeak.net) Date: Sat, 20 May 2006 16:37:29 +0200 (CEST) Subject: [pypy-svn] r27508 - in pypy/dist/pypy/rpython/lltypesystem: . test Message-ID: <20060520143729.0B7B310070@code0.codespeak.net> Author: mwh Date: Sat May 20 16:37:21 2006 New Revision: 27508 Modified: pypy/dist/pypy/rpython/lltypesystem/llmemory.py pypy/dist/pypy/rpython/lltypesystem/test/test_llmemory.py Log: a better implementation of fakeaddress.__eq__ Modified: pypy/dist/pypy/rpython/lltypesystem/llmemory.py ============================================================================== --- pypy/dist/pypy/rpython/lltypesystem/llmemory.py (original) +++ pypy/dist/pypy/rpython/lltypesystem/llmemory.py Sat May 20 16:37:21 2006 @@ -219,6 +219,10 @@ return self.array[self.index] def set(self, value): self.array[self.index] = value + def __eq__(self, other): + if self.__class__ is not other.__class__: + return False + return self.array is other.array and self.index == other.index def type(self): return lltype.typeOf(self.array).TO.OF @@ -230,6 +234,10 @@ def set(self, value): if value != len(self.array): raise Exception("can't change the length of an array") + def __eq__(self, other): + if self.__class__ is not other.__class__: + return False + return self.array is other.array def type(self): return lltype.Signed @@ -241,6 +249,10 @@ return getattr(self.struct, self.fieldname) def set(self, value): setattr(self.struct, self.fieldname, value) + def __eq__(self, other): + if self.__class__ is not other.__class__: + return False + return self.struct is other.struct and self.fieldname == other.fieldname def type(self): return getattr(lltype.typeOf(self.struct).TO, self.fieldname) @@ -251,6 +263,10 @@ return self.ob def set(self, value): raise Exception("can't assign to whole object") + def __eq__(self, other): + if self.__class__ is not other.__class__: + return False + return self.ob is other.ob def type(self): return lltype.typeOf(self.ob) @@ -323,10 +339,7 @@ return other.ob is None if other.ob is None: return False - ref1 = self.ref() - ref2 = other.ref() - return (ref1.__class__ is ref2.__class__ and - ref1.__dict__ == ref2.__dict__) + return self.ref() == other.ref() def __ne__(self, other): return not (self == other) Modified: pypy/dist/pypy/rpython/lltypesystem/test/test_llmemory.py ============================================================================== --- pypy/dist/pypy/rpython/lltypesystem/test/test_llmemory.py (original) +++ pypy/dist/pypy/rpython/lltypesystem/test/test_llmemory.py Sat May 20 16:37:21 2006 @@ -85,6 +85,24 @@ res = interpret(f, []) assert res +def test_fakeaddress_equality(): + S = lltype.GcStruct('S', ('x', lltype.Signed)) + T = lltype.GcStruct('T', ('y', lltype.Signed)) + + s1 = lltype.malloc(S) + s1.x = 1 + s2 = lltype.malloc(S) + s2.x = 1 + t = lltype.malloc(T) + t.y = 1 + + a1s1, a2s1, as2, at = map(cast_ptr_to_adr, [s1, s1, s2, t]) + assert a1s1 == a2s1 + assert a1s1 != as2 + assert a1s1 != at + assert as2 != at + + def test_cast_adr_to_int(): from pypy.rpython.memory.test.test_llinterpsim import interpret S = lltype.GcStruct("S", ("x", lltype.Signed)) From mwh at codespeak.net Sat May 20 17:07:17 2006 From: mwh at codespeak.net (mwh at codespeak.net) Date: Sat, 20 May 2006 17:07:17 +0200 (CEST) Subject: [pypy-svn] r27509 - in pypy/dist/pypy/rpython/memory: . test Message-ID: <20060520150717.4DB7B10070@code0.codespeak.net> Author: mwh Date: Sat May 20 17:07:15 2006 New Revision: 27509 Modified: pypy/dist/pypy/rpython/memory/gc.py pypy/dist/pypy/rpython/memory/gctransform.py pypy/dist/pypy/rpython/memory/test/test_transformed_gc.py Log: a rather cheating implementation of x_become, basically copying collect() and adding a couple of choice lines. however it fails, in a way that doesn't seem to make much sense, even if you make the body of x_become() exactly like that of collect() -- it seems the frame chains get corrupted or something :( Modified: pypy/dist/pypy/rpython/memory/gc.py ============================================================================== --- pypy/dist/pypy/rpython/memory/gc.py (original) +++ pypy/dist/pypy/rpython/memory/gc.py Sat May 20 17:07:15 2006 @@ -456,7 +456,146 @@ clonedata.pool = self.x_swap_pool(curpool) def x_become(self, target_addr, source_addr): - pass + # become is implemented very very much like collect currently... + import os, time + if DEBUG_PRINT: + os.write(2, 'becoming...\n') + start_time = time.time() + roots = self.get_roots() + size_gc_header = self.gcheaderbuilder.size_gc_header + objects = self.AddressLinkedList() + while 1: + curr = roots.pop() +## print "root: ", curr + if curr == NULL: + break + # roots is a list of addresses to addresses: + # ------------------------------------------------- + # begin difference from collect + if curr.address[0] == target_addr: + raise RuntimeError("can't replace a root") + # end difference from collect + # ------------------------------------------------- + objects.append(curr.address[0]) + # the last sweep did not clear the mark bit of static roots, + # since they are not in the malloced_objects list + gc_info = curr.address[0] - size_gc_header + hdr = llmemory.cast_adr_to_ptr(gc_info, self.HDRPTR) + hdr.typeid = hdr.typeid & (~1) + free_non_gc_object(roots) + # from this point onwards, no more mallocs should be possible + old_malloced = self.bytes_malloced + self.bytes_malloced = 0 + while objects.non_empty(): #mark + curr = objects.pop() +## print "object: ", curr + gc_info = curr - size_gc_header + hdr = llmemory.cast_adr_to_ptr(gc_info, self.HDRPTR) + if hdr.typeid & 1: + continue + typeid = hdr.typeid >> 1 + offsets = self.offsets_to_gc_pointers(typeid) + i = 0 + while i < len(offsets): + pointer = curr + offsets[i] + objects.append(pointer.address[0]) + # ------------------------------------------------- + # begin difference from collect + if pointer.address[0] == target_addr: + pointer.address[0] == source_addr + # end difference from collect + # ------------------------------------------------- + i += 1 + if self.is_varsize(typeid): + offset = self.varsize_offset_to_variable_part( + typeid) + length = (curr + self.varsize_offset_to_length(typeid)).signed[0] + curr += offset + offsets = self.varsize_offsets_to_gcpointers_in_var_part(typeid) + itemlength = self.varsize_item_sizes(typeid) + i = 0 + while i < length: + item = curr + itemlength * i + j = 0 + while j < len(offsets): + objects.append((item + offsets[j]).address[0]) + # ------------------------------------------------- + # begin difference from collect + pointer = item + offsets[j] + if pointer.address[0] == target_addr: + pointer.address[0] == source_addr + ## end difference from collect + # ------------------------------------------------- + j += 1 + i += 1 + hdr.typeid = hdr.typeid | 1 + objects.delete() + # also mark self.curpool + if self.curpool: + gc_info = llmemory.cast_ptr_to_adr(self.curpool) - size_gc_header + hdr = llmemory.cast_adr_to_ptr(gc_info, self.HDRPTR) + hdr.typeid = hdr.typeid | 1 + + curr_heap_size = 0 + freed_size = 0 + firstpoolnode = lltype.malloc(self.POOLNODE, flavor='raw') + firstpoolnode.linkedlist = self.malloced_objects + firstpoolnode.nextnode = self.poolnodes + prevpoolnode = lltype.nullptr(self.POOLNODE) + poolnode = firstpoolnode + while poolnode: #sweep + ppnext = lltype.direct_fieldptr(poolnode, 'linkedlist') + hdr = poolnode.linkedlist + while hdr: #sweep + typeid = hdr.typeid >> 1 + next = hdr.next + addr = llmemory.cast_ptr_to_adr(hdr) + size = self.fixed_size(typeid) + if self.is_varsize(typeid): + length = (addr + size_gc_header + self.varsize_offset_to_length(typeid)).signed[0] + size += self.varsize_item_sizes(typeid) * length + estimate = raw_malloc_usage(size_gc_header + size) + if hdr.typeid & 1: + hdr.typeid = hdr.typeid & (~1) + ppnext[0] = hdr + ppnext = lltype.direct_fieldptr(hdr, 'next') + curr_heap_size += estimate + else: + freed_size += estimate + raw_free(addr) + hdr = next + ppnext[0] = lltype.nullptr(self.HDR) + next = poolnode.nextnode + if not poolnode.linkedlist and prevpoolnode: + # completely empty node + prevpoolnode.nextnode = next + lltype.free(poolnode, flavor='raw') + else: + prevpoolnode = poolnode + poolnode = next + self.malloced_objects = firstpoolnode.linkedlist + self.poolnodes = firstpoolnode.nextnode + lltype.free(firstpoolnode, flavor='raw') + + if curr_heap_size > self.bytes_malloced_threshold: + self.bytes_malloced_threshold = curr_heap_size + end_time = time.time() + self.total_collection_time += end_time - start_time + # warning, the following debug prints allocate memory to manipulate + # the strings! so they must be at the end + if DEBUG_PRINT: + os.write(2, " malloced since previous collection: %s bytes\n" % + old_malloced) + os.write(2, " heap usage at start of collection: %s bytes\n" % + (self.heap_usage + old_malloced)) + os.write(2, " freed: %s bytes\n" % + freed_size) + os.write(2, " new heap usage: %s bytes\n" % + curr_heap_size) + os.write(2, " total time spent collecting: %s seconds\n" % + self.total_collection_time) + assert self.heap_usage + old_malloced == curr_heap_size + freed_size + self.heap_usage = curr_heap_size class SemiSpaceGC(GCBase): _alloc_flavor_ = "raw" Modified: pypy/dist/pypy/rpython/memory/gctransform.py ============================================================================== --- pypy/dist/pypy/rpython/memory/gctransform.py (original) +++ pypy/dist/pypy/rpython/memory/gctransform.py Sat May 20 17:07:15 2006 @@ -1197,7 +1197,9 @@ [self.x_become_ptr, self.c_const_gc, v_target, v_source], op.result) - return [newop] + ops, index = self.protect_roots(newop, livevars, block, + block.operations.index(op)) + return ops def push_alive_nopyobj(self, var): return [] Modified: pypy/dist/pypy/rpython/memory/test/test_transformed_gc.py ============================================================================== --- pypy/dist/pypy/rpython/memory/test/test_transformed_gc.py (original) +++ pypy/dist/pypy/rpython/memory/test/test_transformed_gc.py Sat May 20 17:07:15 2006 @@ -335,6 +335,7 @@ GC_PARAMS = {'start_heap_size': 4096 } def test_x_become(self): + py.test.skip('fails mysteriously') S = lltype.GcStruct("S", ('x', lltype.Signed)) def f(): x = lltype.malloc(S) @@ -342,6 +343,7 @@ y = lltype.malloc(S) y.x = 20 z = x + #llop.gc__collect(lltype.Void) llop.gc_x_become(lltype.Void, llmemory.cast_ptr_to_adr(x), llmemory.cast_ptr_to_adr(y)) @@ -349,7 +351,7 @@ run = self.runner(f) res = run([]) # not implemented yet! - #assert res == 20 + assert res == 20 def test_tree_cloning(self): py.test.skip("aaaaaaaaaaaaaaaaaaaaaaargh later") From mwh at codespeak.net Sat May 20 17:38:29 2006 From: mwh at codespeak.net (mwh at codespeak.net) Date: Sat, 20 May 2006 17:38:29 +0200 (CEST) Subject: [pypy-svn] r27510 - pypy/dist/pypy/rpython/memory Message-ID: <20060520153829.803D610070@code0.codespeak.net> Author: mwh Date: Sat May 20 17:38:27 2006 New Revision: 27510 Modified: pypy/dist/pypy/rpython/memory/gctransform.py Log: couple of changes to make gc_x_become to make it more similar to gc__collect; doesn't help though Modified: pypy/dist/pypy/rpython/memory/gctransform.py ============================================================================== --- pypy/dist/pypy/rpython/memory/gctransform.py (original) +++ pypy/dist/pypy/rpython/memory/gctransform.py Sat May 20 17:38:27 2006 @@ -735,7 +735,8 @@ class CollectAnalyzer(graphanalyze.GraphAnalyzer): def operation_is_true(self, op): - return op.opname in ("malloc", "malloc_varsize", "gc__collect") + return op.opname in ("malloc", "malloc_varsize", "gc__collect", + "gc_x_become") class FrameworkGCTransformer(GCTransformer): use_stackless = False @@ -906,8 +907,7 @@ self.x_become_ptr = getfn( GCClass.x_become.im_func, [s_gc, annmodel.SomeAddress(), annmodel.SomeAddress()], - annmodel.s_None, - minimal_transform = False) + annmodel.s_None) annhelper.finish() # at this point, annotate all mix-level helpers annhelper.backend_optimize() From cfbolz at codespeak.net Sat May 20 17:38:40 2006 From: cfbolz at codespeak.net (cfbolz at codespeak.net) Date: Sat, 20 May 2006 17:38:40 +0200 (CEST) Subject: [pypy-svn] r27511 - pypy/dist/pypy/rpython/lltypesystem Message-ID: <20060520153840.50AE510070@code0.codespeak.net> Author: cfbolz Date: Sat May 20 17:38:38 2006 New Revision: 27511 Modified: pypy/dist/pypy/rpython/lltypesystem/llmemory.py Log: this is really a dangling pointer, not an access to NULL Modified: pypy/dist/pypy/rpython/lltypesystem/llmemory.py ============================================================================== --- pypy/dist/pypy/rpython/lltypesystem/llmemory.py (original) +++ pypy/dist/pypy/rpython/lltypesystem/llmemory.py Sat May 20 17:38:38 2006 @@ -394,6 +394,9 @@ class NullAddressError(Exception): pass +class DanglingPointerError(Exception): + pass + NULL = fakeaddress(None) NULL.intaddress = 0 # this is to make memory.lladdress more happy Address = lltype.Primitive("Address", NULL) @@ -485,7 +488,7 @@ return None ob = self.ref() if ob is None: - raise NullAddressError + raise DanglingPointerError return ob def __repr__(self): if self.ref is None: From arigo at codespeak.net Sat May 20 18:37:32 2006 From: arigo at codespeak.net (arigo at codespeak.net) Date: Sat, 20 May 2006 18:37:32 +0200 (CEST) Subject: [pypy-svn] r27512 - in pypy/dist/pypy: rpython rpython/lltypesystem rpython/memory translator/tool Message-ID: <20060520163732.B905110070@code0.codespeak.net> Author: arigo Date: Sat May 20 18:37:29 2006 New Revision: 27512 Added: pypy/dist/pypy/translator/tool/lltracker.py (contents, props changed) Modified: pypy/dist/pypy/rpython/llinterp.py pypy/dist/pypy/rpython/lltypesystem/lloperation.py pypy/dist/pypy/rpython/memory/gcheader.py pypy/dist/pypy/translator/tool/reftracker.py Log: A pygame viewer for lltype data structures. There is an lloperation that will display one or several pointers or addresses, and you click your way along further pointers. Used from llhelpers as: from pypy.rpython.lltypesystem.lloperation import llop llop.debug_view(lltype.Void, myptr [, myptr...]) Modified: pypy/dist/pypy/rpython/llinterp.py ============================================================================== --- pypy/dist/pypy/rpython/llinterp.py (original) +++ pypy/dist/pypy/rpython/llinterp.py Sat May 20 18:37:29 2006 @@ -401,6 +401,10 @@ # __________________________________________________________ # misc LL operation implementations + def op_debug_view(self, *ll_objects): + from pypy.translator.tool.lltracker import track + track(*ll_objects) + def op_keepalive(self, value): pass Modified: pypy/dist/pypy/rpython/lltypesystem/lloperation.py ============================================================================== --- pypy/dist/pypy/rpython/lltypesystem/lloperation.py (original) +++ pypy/dist/pypy/rpython/lltypesystem/lloperation.py Sat May 20 18:37:29 2006 @@ -341,6 +341,9 @@ 'decode_arg': LLOp(canraise=(Exception,)), 'decode_arg_def': LLOp(canraise=(Exception,)), 'getslice': LLOp(canraise=(Exception,)), + + # __________ debugging __________ + 'debug_view': LLOp(), } # __________ operations on PyObjects __________ Modified: pypy/dist/pypy/rpython/memory/gcheader.py ============================================================================== --- pypy/dist/pypy/rpython/memory/gcheader.py (original) +++ pypy/dist/pypy/rpython/memory/gcheader.py Sat May 20 18:37:29 2006 @@ -2,20 +2,23 @@ from pypy.rpython.lltypesystem import lltype, llmemory +# this is global because a header cannot be a header of more than one GcObj +header2obj = weakref.WeakKeyDictionary() + + class GCHeaderBuilder(object): def __init__(self, HDR): """NOT_RPYTHON""" self.HDR = HDR self.obj2header = weakref.WeakKeyDictionary() - self.header2obj = weakref.WeakKeyDictionary() self.size_gc_header = llmemory.GCHeaderOffset(self) def header_of_object(self, gcptr): return self.obj2header[gcptr._as_obj()] def object_from_header(self, headerptr): - return self.header2obj[headerptr._as_obj()] + return header2obj[headerptr._as_obj()] def get_header(self, gcptr): return self.obj2header.get(gcptr._as_obj(), None) @@ -29,7 +32,7 @@ assert not gcobj._parentstructure() headerptr = lltype.malloc(self.HDR, immortal=True) self.obj2header[gcobj] = headerptr - self.header2obj[headerptr._obj] = gcptr._as_ptr() + header2obj[headerptr._obj] = gcptr._as_ptr() return headerptr def _freeze_(self): Added: pypy/dist/pypy/translator/tool/lltracker.py ============================================================================== --- (empty file) +++ pypy/dist/pypy/translator/tool/lltracker.py Sat May 20 18:37:29 2006 @@ -0,0 +1,122 @@ +""" +Reference tracker for lltype data structures. +""" + +import autopath, sys, os +import gc +from pypy.rpython.lltypesystem import lltype, llmemory +from pypy.rpython.memory.gcheader import header2obj +from pypy.translator.tool.reftracker import BaseRefTrackerPage, MARKER +from pypy.tool.uid import uid + + +class LLRefTrackerPage(BaseRefTrackerPage): + + def formatobject(self, o): + lines = [] + for name, value in self.enum_content(o): + if not isinstance(value, str): + value = '0x%x' % uid(value) + lines.append('%s = %s' % (name, value)) + s = '\n'.join(lines) + t = shorttypename(lltype.typeOf(o)) + return t, s, '' + + def get_referrers(self, o): + return [] # not implemented + + def get_referents(self, o): + for name, value in self.enum_content(o): + if not isinstance(value, str): + yield value + + def edgelabel(self, o1, o2): + slst = [] + for name, value in self.enum_content(o1): + if value is o2: + slst.append(name) + return '/'.join(slst) + + def enum_content(cls, o, name=''): + T = lltype.typeOf(o) + if isinstance(T, lltype.Struct): + try: + gcobjptr = header2obj[o] + fmt = '(%s)' + except KeyError: + gcobjptr = None + fmt = '%s' + for name in T._names: + for name, value in cls.enum_content(getattr(o, name), name): + yield fmt % (name,), value + if gcobjptr: + GCT = lltype.typeOf(gcobjptr) + yield 'header of', '<%s>' % (shorttypename(GCT.TO),) + for sub in cls.enum_content(gcobjptr._obj): + yield sub + elif isinstance(T, lltype.Array): + for index, o1 in enumerate(o.items): + for sub in cls.enum_content(o1, str(index)): + yield sub + elif isinstance(T, lltype.Ptr): + if not o: + yield name, 'null' + else: + yield name, o._obj + elif isinstance(T, lltype.OpaqueType) and hasattr(o, 'container'): + T = lltype.typeOf(o.container) + yield 'container', '<%s>' % (shorttypename(T),) + for sub in cls.enum_content(o.container, name): + yield sub + elif T == llmemory.Address: + if not o: + yield name, 'NULL' + else: + addrof = o.get() + T1 = lltype.typeOf(addrof) + if (isinstance(T1, lltype.Ptr) and + isinstance(T1.TO, lltype.Struct) and + addrof._obj in header2obj): + yield name + ' @hdr', addrof._obj + else: + yield name + ' @', o.ob._obj + if o.offset: + yield '... offset', str(o.offset) + else: + yield name, str(o) + enum_content = classmethod(enum_content) + +def shorttypename(T): + return '%s %s' % (T.__class__.__name__, getattr(T, '__name__', '')) + + +def track(*ll_objects): + """Invoke a dot+pygame object reference tracker.""" + lst = [MARKER] + for ll_object in ll_objects: + if isinstance(lltype.typeOf(ll_object), lltype.Ptr): + ll_object = ll_object._obj + lst.append(ll_object) + if len(ll_objects) == 1: + # auto-expand one level + for name, value in LLRefTrackerPage.enum_content(ll_objects[0]): + if not isinstance(value, str): + lst.append(value) + page = LLRefTrackerPage(lst) + page.display() + + +if __name__ == '__main__': + try: + sys.path.remove(os.getcwd()) + except ValueError: + pass + T = lltype.GcArray(lltype.Signed) + S = lltype.GcForwardReference() + S.become(lltype.GcStruct('S', ('t', lltype.Ptr(T)), + ('next', lltype.Ptr(S)))) + s = lltype.malloc(S) + s.next = lltype.malloc(S) + s.next.t = lltype.malloc(T, 5) + s.next.t[1] = 123 + track(s) Modified: pypy/dist/pypy/translator/tool/reftracker.py ============================================================================== --- pypy/dist/pypy/translator/tool/reftracker.py (original) +++ pypy/dist/pypy/translator/tool/reftracker.py Sat May 20 18:37:29 2006 @@ -3,7 +3,7 @@ Usage: call track(obj). """ -import autopath +import autopath, sys, os import gc from pypy.translator.tool.graphpage import GraphPage, DotGen from pypy.tool.uid import uid @@ -12,7 +12,7 @@ MARKER = object() -class RefTrackerPage(GraphPage): +class BaseRefTrackerPage(GraphPage): def compute(self, objectlist): assert objectlist[0] is MARKER @@ -24,36 +24,24 @@ def addedge(o1, o2): key = (uid(o1), uid(o2)) - slst = [] - if type(o1) in (list, tuple): - for i in range(len(o1)): - if o1[i] is o2: - slst.append('[%d]' % i) - elif type(o1) is dict: - for k, v in o1.items(): - if v is o2: - slst.append('[%r]' % (k,)) - edges[key] = ', '.join(slst) + edges[key] = self.edgelabel(o1, o2) for i in range(1, len(objectlist)): - s = repr(objectlist[i]) + typename, s, linktext = self.formatobject(objectlist[i]) word = '0x%x' % uid(objectlist[i]) - if len(s) > 50: - self.links[word] = s - s = s[:20] + ' ... ' + s[-20:] - s = '<%s> %s\\n%s' % (type(objectlist[i]).__name__, - word, - s) + if linktext: + self.links[word] = linktext + s = '<%s> %s\\n%s' % (typename, word, s) nodename = 'node%d' % len(nodes) dotgen.emit_node(nodename, label=s, shape="box") nodes[uid(objectlist[i])] = nodename - for o2 in gc.get_referents(objectlist[i]): + for o2 in self.get_referents(objectlist[i]): if o2 is None: continue addedge(objectlist[i], o2) id2typename[uid(o2)] = type(o2).__name__ del o2 - for o2 in gc.get_referrers(objectlist[i]): + for o2 in self.get_referrers(objectlist[i]): if o2 is None: continue if type(o2) is list and o2 and o2[0] is MARKER: @@ -81,26 +69,60 @@ found = None objectlist = self.objectlist for i in range(1, len(objectlist)): - for o2 in gc.get_referents(objectlist[i]): + for o2 in self.get_referents(objectlist[i]): if uid(o2) == id1: found = o2 - for o2 in gc.get_referrers(objectlist[i]): + for o2 in self.get_referrers(objectlist[i]): if uid(o2) == id1: found = o2 if found is not None: objectlist = objectlist + [found] else: print '*** NOTE: object not found' - return RefTrackerPage(objectlist) + return self.__class__(objectlist) + + def formatobject(self, o): + s = repr(o) + if len(s) > 50: + linktext = s + s = s[:20] + ' ... ' + s[-20:] + else: + linktext = '' + return type(o).__name__, s, linktext + + def edgelabel(self, o1, o2): + return '' + + +class RefTrackerPage(BaseRefTrackerPage): + + get_referrers = staticmethod(gc.get_referrers) + get_referents = staticmethod(gc.get_referents) + + def edgelabel(self, o1, o2): + slst = [] + if type(o1) in (list, tuple): + for i in range(len(o1)): + if o1[i] is o2: + slst.append('[%d]' % i) + elif type(o1) is dict: + for k, v in o1.items(): + if v is o2: + slst.append('[%r]' % (k,)) + return ', '.join(slst) -def track(o): +def track(*objs): """Invoke a dot+pygame object reference tracker.""" - page = RefTrackerPage([MARKER, o]) - del o + page = RefTrackerPage([MARKER] + list(objs)) + del objs page.display() if __name__ == '__main__': + try: + sys.path.remove(os.getcwd()) + except ValueError: + pass d = {"lskjadldjslkj": "adjoiadoixmdoiemdwoi"} track(d) From arigo at codespeak.net Sat May 20 19:30:13 2006 From: arigo at codespeak.net (arigo at codespeak.net) Date: Sat, 20 May 2006 19:30:13 +0200 (CEST) Subject: [pypy-svn] r27514 - pypy/dist/pypy/translator/tool Message-ID: <20060520173013.98A4F1006B@code0.codespeak.net> Author: arigo Date: Sat May 20 19:30:12 2006 New Revision: 27514 Modified: pypy/dist/pypy/translator/tool/lltracker.py pypy/dist/pypy/translator/tool/reftracker.py Log: (pedronis sleepy, arigo) Debugging the debugger. (fight fight fight) Modified: pypy/dist/pypy/translator/tool/lltracker.py ============================================================================== --- pypy/dist/pypy/translator/tool/lltracker.py (original) +++ pypy/dist/pypy/translator/tool/lltracker.py Sat May 20 19:30:12 2006 @@ -12,6 +12,10 @@ class LLRefTrackerPage(BaseRefTrackerPage): + def compute(self, objectlist, size_gc_header): + self.size_gc_header = size_gc_header + return BaseRefTrackerPage.compute(self, objectlist) + def formatobject(self, o): lines = [] for name, value in self.enum_content(o): @@ -37,8 +41,18 @@ slst.append(name) return '/'.join(slst) - def enum_content(cls, o, name=''): + def newpage(self, objectlist): + return self.__class__(objectlist, self.size_gc_header) + + def enum_content(self, o, name='', with_header=True): + # XXX clean up T = lltype.typeOf(o) + if (self.size_gc_header is not None and with_header + and isinstance(T, lltype.GC_CONTAINER)): + adr = llmemory.cast_ptr_to_adr(o._as_ptr()) + adr -= self.size_gc_header + o = adr.get()._obj + T = lltype.typeOf(o) if isinstance(T, lltype.Struct): try: gcobjptr = header2obj[o] @@ -47,26 +61,33 @@ gcobjptr = None fmt = '%s' for name in T._names: - for name, value in cls.enum_content(getattr(o, name), name): + for name, value in self.enum_content(getattr(o, name), name, + with_header=False): yield fmt % (name,), value if gcobjptr: GCT = lltype.typeOf(gcobjptr) - yield 'header of', '<%s>' % (shorttypename(GCT.TO),) - for sub in cls.enum_content(gcobjptr._obj): - yield sub + if self.size_gc_header is not None: + yield 'header of', '<%s>' % (shorttypename(GCT.TO),) + for sub in self.enum_content(gcobjptr._obj, + with_header=False): + yield sub + else: + # display as a link to avoid the same data showing up + # twice in the graph + yield 'header of', gcobjptr._obj elif isinstance(T, lltype.Array): for index, o1 in enumerate(o.items): - for sub in cls.enum_content(o1, str(index)): + for sub in self.enum_content(o1, str(index)): yield sub elif isinstance(T, lltype.Ptr): if not o: yield name, 'null' else: - yield name, o._obj + yield name, lltype.normalizeptr(o)._obj elif isinstance(T, lltype.OpaqueType) and hasattr(o, 'container'): T = lltype.typeOf(o.container) yield 'container', '<%s>' % (shorttypename(T),) - for sub in cls.enum_content(o.container, name): + for sub in self.enum_content(o.container, name, with_header=False): yield sub elif T == llmemory.Address: if not o: @@ -84,7 +105,6 @@ yield '... offset', str(o.offset) else: yield name, str(o) - enum_content = classmethod(enum_content) def shorttypename(T): return '%s %s' % (T.__class__.__name__, getattr(T, '__name__', '')) @@ -93,16 +113,23 @@ def track(*ll_objects): """Invoke a dot+pygame object reference tracker.""" lst = [MARKER] + size_gc_header = None for ll_object in ll_objects: + if isinstance(ll_object, llmemory.GCHeaderOffset): + size_gc_header = ll_object + continue if isinstance(lltype.typeOf(ll_object), lltype.Ptr): - ll_object = ll_object._obj - lst.append(ll_object) - if len(ll_objects) == 1: + ll_object = lltype.normalizeptr(ll_object)._obj + if ll_object not in lst: + lst.append(ll_object) + page = LLRefTrackerPage(lst, size_gc_header) + if len(lst) == 2: # auto-expand one level - for name, value in LLRefTrackerPage.enum_content(ll_objects[0]): - if not isinstance(value, str): + page = page.content() + for name, value in page.enum_content(lst[1]): + if not isinstance(value, str) and value not in lst: lst.append(value) - page = LLRefTrackerPage(lst) + page = page.newpage(lst) page.display() Modified: pypy/dist/pypy/translator/tool/reftracker.py ============================================================================== --- pypy/dist/pypy/translator/tool/reftracker.py (original) +++ pypy/dist/pypy/translator/tool/reftracker.py Sat May 20 19:30:12 2006 @@ -79,7 +79,7 @@ objectlist = objectlist + [found] else: print '*** NOTE: object not found' - return self.__class__(objectlist) + return self.newpage(objectlist) def formatobject(self, o): s = repr(o) @@ -93,6 +93,9 @@ def edgelabel(self, o1, o2): return '' + def newpage(self, objectlist): + return self.__class__(objectlist) + class RefTrackerPage(BaseRefTrackerPage): From arigo at codespeak.net Sat May 20 19:46:45 2006 From: arigo at codespeak.net (arigo at codespeak.net) Date: Sat, 20 May 2006 19:46:45 +0200 (CEST) Subject: [pypy-svn] r27515 - pypy/dist/pypy/translator/tool Message-ID: <20060520174645.BA06810070@code0.codespeak.net> Author: arigo Date: Sat May 20 19:46:44 2006 New Revision: 27515 Modified: pypy/dist/pypy/translator/tool/lltracker.py Log: More fight fight fight. Modified: pypy/dist/pypy/translator/tool/lltracker.py ============================================================================== --- pypy/dist/pypy/translator/tool/lltracker.py (original) +++ pypy/dist/pypy/translator/tool/lltracker.py Sat May 20 19:46:44 2006 @@ -44,6 +44,14 @@ def newpage(self, objectlist): return self.__class__(objectlist, self.size_gc_header) + def normalize(self, o): + if self.size_gc_header is not None: + try: + return header2obj[o]._obj + except (KeyError, TypeError): + pass + return o + def enum_content(self, o, name='', with_header=True): # XXX clean up T = lltype.typeOf(o) @@ -67,7 +75,6 @@ if gcobjptr: GCT = lltype.typeOf(gcobjptr) if self.size_gc_header is not None: - yield 'header of', '<%s>' % (shorttypename(GCT.TO),) for sub in self.enum_content(gcobjptr._obj, with_header=False): yield sub @@ -83,7 +90,7 @@ if not o: yield name, 'null' else: - yield name, lltype.normalizeptr(o)._obj + yield name, self.normalize(lltype.normalizeptr(o)._obj) elif isinstance(T, lltype.OpaqueType) and hasattr(o, 'container'): T = lltype.typeOf(o.container) yield 'container', '<%s>' % (shorttypename(T),) @@ -98,9 +105,9 @@ if (isinstance(T1, lltype.Ptr) and isinstance(T1.TO, lltype.Struct) and addrof._obj in header2obj): - yield name + ' @hdr', addrof._obj + yield name + ' @hdr', self.normalize(addrof._obj) else: - yield name + ' @', o.ob._obj + yield name + ' @', self.normalize(o.ob._obj) if o.offset: yield '... offset', str(o.offset) else: From arigo at codespeak.net Sat May 20 21:02:14 2006 From: arigo at codespeak.net (arigo at codespeak.net) Date: Sat, 20 May 2006 21:02:14 +0200 (CEST) Subject: [pypy-svn] r27516 - pypy/dist/pypy/rpython/memory Message-ID: <20060520190214.6F0D810070@code0.codespeak.net> Author: arigo Date: Sat May 20 21:02:13 2006 New Revision: 27516 Modified: pypy/dist/pypy/rpython/memory/gc.py Log: Somehow a fix. But only because the lladdress simulator doesn't know about direct_fieldptr(). Kill! Modified: pypy/dist/pypy/rpython/memory/gc.py ============================================================================== --- pypy/dist/pypy/rpython/memory/gc.py (original) +++ pypy/dist/pypy/rpython/memory/gc.py Sat May 20 21:02:13 2006 @@ -267,7 +267,8 @@ prevpoolnode = lltype.nullptr(self.POOLNODE) poolnode = firstpoolnode while poolnode: #sweep - ppnext = lltype.direct_fieldptr(poolnode, 'linkedlist') + ppnext = llmemory.cast_ptr_to_adr(poolnode) + ppnext += llmemory.offsetof(self.POOLNODE, 'linkedlist') hdr = poolnode.linkedlist while hdr: #sweep typeid = hdr.typeid >> 1 @@ -280,14 +281,15 @@ estimate = raw_malloc_usage(size_gc_header + size) if hdr.typeid & 1: hdr.typeid = hdr.typeid & (~1) - ppnext[0] = hdr - ppnext = lltype.direct_fieldptr(hdr, 'next') + ppnext.address[0] = addr + ppnext = llmemory.cast_ptr_to_adr(hdr) + ppnext += llmemory.offsetof(self.HDR, 'next') curr_heap_size += estimate else: freed_size += estimate raw_free(addr) hdr = next - ppnext[0] = lltype.nullptr(self.HDR) + ppnext.address[0] = llmemory.NULL next = poolnode.nextnode if not poolnode.linkedlist and prevpoolnode: # completely empty node From arigo at codespeak.net Sat May 20 21:29:09 2006 From: arigo at codespeak.net (arigo at codespeak.net) Date: Sat, 20 May 2006 21:29:09 +0200 (CEST) Subject: [pypy-svn] r27517 - in pypy/dist/pypy: rpython rpython/lltypesystem rpython/memory translator/c Message-ID: <20060520192909.4231F10070@code0.codespeak.net> Author: arigo Date: Sat May 20 21:29:06 2006 New Revision: 27517 Modified: pypy/dist/pypy/rpython/llinterp.py pypy/dist/pypy/rpython/lltypesystem/lloperation.py pypy/dist/pypy/rpython/memory/gc.py pypy/dist/pypy/rpython/memory/gctransform.py pypy/dist/pypy/translator/c/funcgen.py pypy/dist/pypy/translator/c/support.py Log: (pedronis, arigo) Added a 'debug_print' low-level operation. Saner than using os.write() for debugging the gc, because os.write() requires allocating strings for the formatting... This operation also produces reasonable-looking C code. Modified: pypy/dist/pypy/rpython/llinterp.py ============================================================================== --- pypy/dist/pypy/rpython/llinterp.py (original) +++ pypy/dist/pypy/rpython/llinterp.py Sat May 20 21:29:06 2006 @@ -405,6 +405,15 @@ from pypy.translator.tool.lltracker import track track(*ll_objects) + def op_debug_print(self, *ll_args): + from pypy.rpython.lltypesystem.rstr import STR + for arg in ll_args: + T = lltype.typeOf(arg) + if T == lltype.Ptr(STR): + arg = ''.join(arg.chars) + print arg, + print + def op_keepalive(self, value): pass Modified: pypy/dist/pypy/rpython/lltypesystem/lloperation.py ============================================================================== --- pypy/dist/pypy/rpython/lltypesystem/lloperation.py (original) +++ pypy/dist/pypy/rpython/lltypesystem/lloperation.py Sat May 20 21:29:06 2006 @@ -319,13 +319,17 @@ 'gc_reload_possibly_moved': LLOp(), # experimental operations in support of thread cloning, only # implemented by the Mark&Sweep GC - 'gc_x_swap_pool': LLOp(canraise=(MemoryError,)), - 'gc_x_clone': LLOp(canraise=(MemoryError,)), + 'gc_x_swap_pool': LLOp(canraise=(Exception,)), + 'gc_x_clone': LLOp(canraise=(Exception,)), + 'gc_x_size_header': LLOp(), # this one is even more experimental; only implemented with the # Mark&Sweep GC, and likely only useful when combined with # stackless: - 'gc_x_become': LLOp(canraise=(RuntimeError,)), - + 'gc_x_become': LLOp(canraise=(Exception,)), + + # NOTE NOTE NOTE! don't forget *** canraise=StackException *** or + # possibly Exception for anything that can unwind the stack, in + # particular anything that mallocs! # __________ stackless operation(s) __________ @@ -344,6 +348,7 @@ # __________ debugging __________ 'debug_view': LLOp(), + 'debug_print': LLOp(), } # __________ operations on PyObjects __________ Modified: pypy/dist/pypy/rpython/memory/gc.py ============================================================================== --- pypy/dist/pypy/rpython/memory/gc.py (original) +++ pypy/dist/pypy/rpython/memory/gc.py Sat May 20 21:29:06 2006 @@ -5,6 +5,7 @@ from pypy.rpython.memory import lltypesimulation from pypy.rpython.lltypesystem import lltype, llmemory from pypy.rpython.objectmodel import free_non_gc_object +from pypy.rpython.lltypesystem.lloperation import llop from pypy.rpython import rarithmetic import sys @@ -199,12 +200,14 @@ return llmemory.cast_adr_to_ptr(result, llmemory.GCREF) def collect(self): - import os, time + import time if DEBUG_PRINT: - os.write(2, 'collecting...\n') + llop.debug_print(lltype.Void, 'collecting...') start_time = time.time() roots = self.get_roots() size_gc_header = self.gcheaderbuilder.size_gc_header +## llop.debug_view(lltype.Void, self.malloced_objects, self.poolnodes, +## size_gc_header) objects = self.AddressLinkedList() while 1: curr = roots.pop() @@ -306,19 +309,24 @@ self.bytes_malloced_threshold = curr_heap_size end_time = time.time() self.total_collection_time += end_time - start_time - # warning, the following debug prints allocate memory to manipulate - # the strings! so they must be at the end if DEBUG_PRINT: - os.write(2, " malloced since previous collection: %s bytes\n" % - old_malloced) - os.write(2, " heap usage at start of collection: %s bytes\n" % - (self.heap_usage + old_malloced)) - os.write(2, " freed: %s bytes\n" % - freed_size) - os.write(2, " new heap usage: %s bytes\n" % - curr_heap_size) - os.write(2, " total time spent collecting: %s seconds\n" % - self.total_collection_time) + llop.debug_print(lltype.Void, + " malloced since previous collection:", + old_malloced, "bytes") + llop.debug_print(lltype.Void, + " heap usage at start of collection: ", + self.heap_usage + old_malloced, "bytes") + llop.debug_print(lltype.Void, + " freed: ", + freed_size, "bytes") + llop.debug_print(lltype.Void, + " new heap usage: ", + curr_heap_size, "bytes") + llop.debug_print(lltype.Void, + " total time spent collecting: ", + self.total_collection_time, "seconds") +## llop.debug_view(lltype.Void, self.malloced_objects, self.poolnodes, +## size_gc_header) assert self.heap_usage + old_malloced == curr_heap_size + freed_size self.heap_usage = curr_heap_size @@ -397,6 +405,7 @@ oldpool = lltype.cast_opaque_ptr(self.POOLPTR, oldpool) addr = llmemory.cast_ptr_to_adr(oldpool) addr -= size_gc_header + hdr = llmemory.cast_adr_to_ptr(addr, self.HDRPTR) hdr = hdr.next # skip the POOL object itself while hdr: Modified: pypy/dist/pypy/rpython/memory/gctransform.py ============================================================================== --- pypy/dist/pypy/rpython/memory/gctransform.py (original) +++ pypy/dist/pypy/rpython/memory/gctransform.py Sat May 20 21:29:06 2006 @@ -1191,6 +1191,13 @@ op.result) return [newop] + def replace_gc_x_size_header(self, op, livevars, block): + c_result = Constant(self.gcdata.gc.size_gc_header(), lltype.Signed) + newop = SpaceOperation("same_as", + [c_result], + op.result) + return [newop] + def replace_gc_x_become(self, op, livevars, block): [v_target, v_source] = op.args newop = SpaceOperation("direct_call", Modified: pypy/dist/pypy/translator/c/funcgen.py ============================================================================== --- pypy/dist/pypy/translator/c/funcgen.py (original) +++ pypy/dist/pypy/translator/c/funcgen.py Sat May 20 21:29:06 2006 @@ -2,10 +2,11 @@ from pypy.translator.c.support import USESLOTS # set to False if necessary while refactoring from pypy.translator.c.support import cdecl, ErrorValue from pypy.translator.c.support import llvalue_from_constant, gen_assignments +from pypy.translator.c.support import c_string_constant from pypy.objspace.flow.model import Variable, Constant, Block from pypy.objspace.flow.model import c_last_exception, copygraph from pypy.rpython.lltypesystem.lltype import Ptr, PyObject, Void, Bool, Signed -from pypy.rpython.lltypesystem.lltype import Unsigned, SignedLongLong +from pypy.rpython.lltypesystem.lltype import Unsigned, SignedLongLong, Float from pypy.rpython.lltypesystem.lltype import UnsignedLongLong, Char, UniChar from pypy.rpython.lltypesystem.lltype import pyobjectptr, ContainerType from pypy.rpython.lltypesystem.lltype import Struct, Array, FixedSizeArray @@ -658,5 +659,37 @@ typename = cdecl(self.db.gettype(TYPE), '') return "%(result)s = (%(typename)s)(%(val)s);" % locals() + def OP_DEBUG_PRINT(self, op): + # XXX + from pypy.rpython.lltypesystem.rstr import STR + format = [] + argv = [] + for arg in op.args: + T = arg.concretetype + if T == Ptr(STR): + if isinstance(arg, Constant): + format.append(''.join(arg.value.chars).replace('%', '%%')) + else: + format.append('%s') + argv.append('RPyString_AsString(%s)' % self.expr(arg)) + continue + elif T == Signed: + format.append('%d') + elif T == Float: + format.append('%f') + elif isinstance(T, Ptr): + format.append('%p') + elif T == Char: + if isinstance(arg, Constant): + format.append(arg.value.replace('%', '%%')) + continue + format.append('%c') + else: + raise Exception("don't know how to debug_print %r" % (T,)) + argv.append(self.expr(arg)) + return "fprintf(stderr, %s%s);" % ( + c_string_constant(' '.join(format) + '\n'), + ''.join([', ' + s for s in argv])) + assert not USESLOTS or '__dict__' not in dir(FunctionCodeGenerator) Modified: pypy/dist/pypy/translator/c/support.py ============================================================================== --- pypy/dist/pypy/translator/c/support.py (original) +++ pypy/dist/pypy/translator/c/support.py Sat May 20 21:29:06 2006 @@ -68,7 +68,7 @@ ''') -def c_string_constant(s): +def c_string_constant(s, force_quote=False): '''Returns EITHER a " "-delimited string literal for C OR a { }-delimited array of chars. ''' @@ -82,7 +82,7 @@ if len(s) < 64: return '"%s"' % line_repr(s) - elif len(s) < 1024: + elif len(s) < 1024 or force_quote: lines = ['"'] for i in range(0, len(s), 32): lines.append(line_repr(s[i:i+32])) From tismer at codespeak.net Sat May 20 21:48:09 2006 From: tismer at codespeak.net (tismer at codespeak.net) Date: Sat, 20 May 2006 21:48:09 +0200 (CEST) Subject: [pypy-svn] r27518 - in pypy/dist/pypy: interpreter/test module/_pickle_support objspace/std Message-ID: <20060520194809.5C63B10070@code0.codespeak.net> Author: tismer Date: Sat May 20 21:48:07 2006 New Revision: 27518 Modified: pypy/dist/pypy/interpreter/test/test_pickle.py pypy/dist/pypy/module/_pickle_support/__init__.py pypy/dist/pypy/module/_pickle_support/maker.py pypy/dist/pypy/objspace/std/dicttype.py Log: implemented pickling of dict iterators. This is in fact a bit hairy since dicts are hairy. We use the same simple approach that Stackless did: pickke a list and build it's iter() Modified: pypy/dist/pypy/interpreter/test/test_pickle.py ============================================================================== --- pypy/dist/pypy/interpreter/test/test_pickle.py (original) +++ pypy/dist/pypy/interpreter/test/test_pickle.py Sat May 20 21:48:07 2006 @@ -190,12 +190,14 @@ assert liter == result def test_pickle_dictiter(self): - skip("work in progress") import pickle - diter = iter({}) + tdict = {'2':2, '3':3, '5':5} + diter = iter(tdict) + diter.next() pckl = pickle.dumps(diter) result = pickle.loads(pckl) - assert diter == result + assert len(diter) == 2 + assert list(diter) == list(result) def test_pickle_enum(self): import pickle Modified: pypy/dist/pypy/module/_pickle_support/__init__.py ============================================================================== --- pypy/dist/pypy/module/_pickle_support/__init__.py (original) +++ pypy/dist/pypy/module/_pickle_support/__init__.py Sat May 20 21:48:07 2006 @@ -12,6 +12,6 @@ 'func_new' : 'maker.func_new', 'module_new' : 'maker.module_new', 'method_new' : 'maker.method_new', - 'dictiter_new' : 'maker.dictiter_new', + 'dictiter_surrogate_new' : 'maker.dictiter_surrogate_new', 'seqiter_new' : 'maker.seqiter_new', } Modified: pypy/dist/pypy/module/_pickle_support/maker.py ============================================================================== --- pypy/dist/pypy/module/_pickle_support/maker.py (original) +++ pypy/dist/pypy/module/_pickle_support/maker.py Sat May 20 21:48:07 2006 @@ -35,17 +35,11 @@ return space.call_args(w_type, __args__) method_new.unwrap_spec = [ObjSpace, Arguments] -def dictiter_new(space, __args__): - from pypy.objspace.std.dictobject import W_DictIterObject - #print "dictiter_new here 1)", space, w_dictitertype, __args__ - w_type = space.gettypeobject(dictiter_typedef) - w_obj = space.allocate_instance(W_DictIterObject, w_type) - #print "dictiter_new here 2)", w_obj - # XXX W_DictIterObject.__init__(w_obj, space) - # this is wrong, but we need to produce something different, anyway - #print "dictiter_new here 3)", w_obj - return w_obj -dictiter_new.unwrap_spec = [ObjSpace, Arguments] +def dictiter_surrogate_new(space, w_lis): + # we got a listobject. + # simply create an iterator and that's it. + return space.iter(w_lis) +dictiter_surrogate_new.unwrap_spec = [ObjSpace, W_Root] #XXX this doesn't work yet def seqiter_new(space, w_seqitertype, __args__): Modified: pypy/dist/pypy/objspace/std/dicttype.py ============================================================================== --- pypy/dist/pypy/objspace/std/dicttype.py (original) +++ pypy/dist/pypy/objspace/std/dicttype.py Sat May 20 21:48:07 2006 @@ -124,13 +124,63 @@ # ____________________________________________________________ -def descr_dictiter__reduce__(space, w_subtype): +def descr_dictiter__reduce__(w_self, space): + """ + This is a slightly special case of pickling. + Since iteration over a dict is a bit hairy, + we do the following: + - create a clone of the dict iterator + - run it to the original position + - collect all remaining elements into a list + At unpickling time, we just use that list + and create an iterator on it. + This is of course not the standard way. + + XXX to do: remove this __reduce__ method and do + a registration with copy_reg, instead. + """ from pypy.interpreter.mixedmodule import MixedModule + from pypy.objspace.std.dictobject import \ + W_DictIter_Keys, W_DictIter_Values, W_DictIter_Items w_mod = space.getbuiltinmodule('_pickle_support') mod = space.interp_w(MixedModule, w_mod) - new_inst = mod.get('dictiter_new') - w = space.wrap + new_inst = mod.get('dictiter_surrogate_new') + w_typeobj = space.gettypeobject(dictiter_typedef) + if isinstance(w_self, W_DictIter_Keys): + w_clone = space.allocate_instance(W_DictIter_Keys, w_typeobj) + elif isinstance(w_self, W_DictIter_Values): + w_clone = space.allocate_instance(W_DictIter_Values, w_typeobj) + elif isinstance(w_self, W_DictIter_Items): + w_clone = space.allocate_instance(W_DictIter_Items, w_typeobj) + # we cannot call __init__ since we don't have the original dict + w_clone.space = space + w_clone.content = w_self.content + w_clone.len = w_self.len + w_clone.pos = 0 + w_clone.setup_iterator() + # spool until we have the same pos + while w_clone.pos < w_self.pos: + w_obj = w_clone.next_entry() + w_clone.pos += 1 + stuff = [w_clone.next_entry() for i in range(w_clone.pos, w_clone.len)] + w_res = space.newlist(stuff) tup = [ + w_res + ] + w_ret = space.newtuple([new_inst, space.newtuple(tup)]) + return w_ret + +# ____________________________________________________________ + + +dictiter_typedef = StdTypeDef("dictionaryiterator", + __reduce__ = gateway.interp2app(descr_dictiter__reduce__, + unwrap_spec=[gateway.W_Root, gateway.ObjSpace]), + ) +#note: registering in dictobject.py + + +### fragment for frame object left here #w(10), #w(self.co_argcount), #w(self.co_nlocals), @@ -147,13 +197,4 @@ #space.newtuple([w(v) for v in self.co_freevars]), #space.newtuple([w(v) for v in self.co_cellvars]), #hidden_applevel=False, magic = 62061 | 0x0a0d0000 - ] - return space.newtuple([new_inst, space.newtuple(tup)]) - -# ____________________________________________________________ -dictiter_typedef = StdTypeDef("dictionaryiterator", - __reduce__ = gateway.interp2app(descr_dictiter__reduce__, - unwrap_spec=[gateway.ObjSpace, gateway.W_Root]), - ) -#note: registering in dictobject.py From arigo at codespeak.net Sat May 20 22:04:53 2006 From: arigo at codespeak.net (arigo at codespeak.net) Date: Sat, 20 May 2006 22:04:53 +0200 (CEST) Subject: [pypy-svn] r27519 - in pypy/dist/pypy: rpython/lltypesystem rpython/memory/test translator/stackless Message-ID: <20060520200453.8787E10070@code0.codespeak.net> Author: arigo Date: Sat May 20 22:04:51 2006 New Revision: 27519 Modified: pypy/dist/pypy/rpython/lltypesystem/lloperation.py pypy/dist/pypy/rpython/memory/test/test_transformed_gc.py pypy/dist/pypy/translator/stackless/transform.py Log: (pedronis, arigo) Yikes! The problem was about the stackless transform. It contained a hard-coded list of operations that can possibly unwind the stack. Moreover, even if it knew about the new gc_x_*() operations, the exception transform would kill the UnwindException branch without a canraise=... in LLOp(). So we added a flag 'canraisegc=True' that prevents both things from going wrong. test_tree_cloning passes now! Cloning seems to be working well enough that we can try to expose it to RPython and see. Modified: pypy/dist/pypy/rpython/lltypesystem/lloperation.py ============================================================================== --- pypy/dist/pypy/rpython/lltypesystem/lloperation.py (original) +++ pypy/dist/pypy/rpython/lltypesystem/lloperation.py Sat May 20 22:04:51 2006 @@ -7,7 +7,8 @@ class LLOp(object): - def __init__(self, sideeffects=True, canfold=False, canraise=(), pyobj=False): + def __init__(self, sideeffects=True, canfold=False, canraise=(), + pyobj=False, canunwindgc=False): # self.opname = ... (set afterwards) if canfold: @@ -28,6 +29,13 @@ # The operation manipulates PyObjects self.pyobj = pyobj + # The operation can unwind the stack in a stackless gc build + self.canunwindgc = canunwindgc + if canunwindgc: + if (StackException not in self.canraise and + Exception not in self.canraise): + self.canraise += (StackException,) + # __________ make the LLOp instances callable from LL helpers __________ __name__ = property(lambda self: 'llop_'+self.opname) @@ -254,8 +262,8 @@ # __________ pointer operations __________ - 'malloc': LLOp(canraise=(MemoryError,)), - 'malloc_varsize': LLOp(canraise=(MemoryError,)), + 'malloc': LLOp(canraise=(MemoryError,), canunwindgc=True), + 'malloc_varsize': LLOp(canraise=(MemoryError,), canunwindgc=True), 'flavored_malloc': LLOp(canraise=(MemoryError,)), 'flavored_free': LLOp(), 'getfield': LLOp(sideeffects=False), @@ -307,7 +315,7 @@ # __________ GC operations __________ - 'gc__collect': LLOp(canraise=(Exception,)), + 'gc__collect': LLOp(canunwindgc=True), 'gc_free': LLOp(), 'gc_fetch_exception': LLOp(), 'gc_restore_exception': LLOp(), @@ -319,21 +327,21 @@ 'gc_reload_possibly_moved': LLOp(), # experimental operations in support of thread cloning, only # implemented by the Mark&Sweep GC - 'gc_x_swap_pool': LLOp(canraise=(Exception,)), - 'gc_x_clone': LLOp(canraise=(Exception,)), + 'gc_x_swap_pool': LLOp(canraise=(MemoryError,), canunwindgc=True), + 'gc_x_clone': LLOp(canraise=(MemoryError,), canunwindgc=True), 'gc_x_size_header': LLOp(), # this one is even more experimental; only implemented with the # Mark&Sweep GC, and likely only useful when combined with # stackless: - 'gc_x_become': LLOp(canraise=(Exception,)), + 'gc_x_become': LLOp(canraise=(RuntimeError,), canunwindgc=True), - # NOTE NOTE NOTE! don't forget *** canraise=StackException *** or - # possibly Exception for anything that can unwind the stack, in - # particular anything that mallocs! + # NOTE NOTE NOTE! don't forget *** canunwindgc=True *** for anything that + # can go through a stack unwind, in particular anything that mallocs! # __________ stackless operation(s) __________ 'yield_current_frame_to_caller': LLOp(canraise=(StackException,)), + # can always unwind, not just if stackless gc # __________ misc operations __________ Modified: pypy/dist/pypy/rpython/memory/test/test_transformed_gc.py ============================================================================== --- pypy/dist/pypy/rpython/memory/test/test_transformed_gc.py (original) +++ pypy/dist/pypy/rpython/memory/test/test_transformed_gc.py Sat May 20 22:04:51 2006 @@ -327,42 +327,17 @@ res = run([]) assert res == 111222333 - -class TestStacklessMarkSweepGC(TestMarkSweepGC): - - class gcpolicy(gc.StacklessFrameworkGcPolicy): - class transformerclass(gctransform.StacklessFrameworkGCTransformer): - GC_PARAMS = {'start_heap_size': 4096 } - - def test_x_become(self): - py.test.skip('fails mysteriously') - S = lltype.GcStruct("S", ('x', lltype.Signed)) - def f(): - x = lltype.malloc(S) - x.x = 10 - y = lltype.malloc(S) - y.x = 20 - z = x - #llop.gc__collect(lltype.Void) - llop.gc_x_become(lltype.Void, - llmemory.cast_ptr_to_adr(x), - llmemory.cast_ptr_to_adr(y)) - return z.x - run = self.runner(f) - res = run([]) - # not implemented yet! - assert res == 20 - def test_tree_cloning(self): - py.test.skip("aaaaaaaaaaaaaaaaaaaaaaargh later") import os # this makes a tree of calls. Each leaf stores its path (a linked # list) in 'result'. Paths are mutated in-place but the leaves don't # see each other's mutations because of x_clone. + STUFF = lltype.FixedSizeArray(lltype.Signed, 21) NODE = lltype.GcForwardReference() NODE.become(lltype.GcStruct('node', ('index', lltype.Signed), ('counter', lltype.Signed), - ('next', lltype.Ptr(NODE)))) + ('next', lltype.Ptr(NODE)), + ('use_some_space', STUFF))) PATHARRAY = lltype.GcArray(lltype.Ptr(NODE)) clonedata = lltype.malloc(X_CLONE) @@ -390,22 +365,23 @@ # The above should have the same effect as: # path = clone(path) - # bump all the path's counters by one + # bump all the path node counters by one p = path while p: p.counter += 1 p = p.next if remaining_depth == 0: + llop.debug_print(lltype.Void, "setting", index, "with", path) result[index] = path # leaf else: node = lltype.malloc(NODE) node.index = index * 2 node.counter = 0 node.next = path - do_call(result, node, node.index, remaining_depth - 1) + do_call(result, node, index * 2, remaining_depth - 1) node.index += 1 # mutation! - do_call(result, node, node.index, remaining_depth - 1) + do_call(result, node, index * 2 + 1, remaining_depth - 1) # restore the parent pool llop.gc_x_swap_pool(X_POOL_PTR, parentpool) @@ -424,14 +400,43 @@ os.write(2, 'building tree... ') do_call(result, lltype.nullptr(NODE), 0, depth) os.write(2, 'checking tree... ') + #from pypy.rpython.lltypesystem.lloperation import llop + #llop.debug_view(lltype.Void, result, + # llop.gc_x_size_header(lltype.Signed)) for i in range(1 << depth): check(result[i], i, 0, depth) os.write(2, 'ok\n') return 1 run = self.runner(func, nbargs=2) - res = run([5, 0]) + res = run([3, 0]) assert res == 1 + +class TestStacklessMarkSweepGC(TestMarkSweepGC): + + class gcpolicy(gc.StacklessFrameworkGcPolicy): + class transformerclass(gctransform.StacklessFrameworkGCTransformer): + GC_PARAMS = {'start_heap_size': 4096 } + + def test_x_become(self): + py.test.skip('fails less mysteriously') + S = lltype.GcStruct("S", ('x', lltype.Signed)) + def f(): + x = lltype.malloc(S) + x.x = 10 + y = lltype.malloc(S) + y.x = 20 + z = x + #llop.gc__collect(lltype.Void) + llop.gc_x_become(lltype.Void, + llmemory.cast_ptr_to_adr(x), + llmemory.cast_ptr_to_adr(y)) + return z.x + run = self.runner(f) + res = run([]) + # not implemented yet! + assert res == 20 + class TestSemiSpaceGC(TestMarkSweepGC): def setup_class(cls): Modified: pypy/dist/pypy/translator/stackless/transform.py ============================================================================== --- pypy/dist/pypy/translator/stackless/transform.py (original) +++ pypy/dist/pypy/translator/stackless/transform.py Sat May 20 22:04:51 2006 @@ -1,4 +1,5 @@ from pypy.rpython.lltypesystem import lltype, llmemory +from pypy.rpython.lltypesystem.lloperation import LL_OPERATIONS from pypy.rpython import rarithmetic, rclass, rmodel from pypy.translator.backendopt import support from pypy.objspace.flow import model @@ -97,9 +98,9 @@ self.stackless_gc = stackless_gc def operation_is_true(self, op): - return (op.opname == 'yield_current_frame_to_caller' or - self.stackless_gc and (op.opname.startswith('malloc') - or op.opname == 'gc__collect')) + if op.opname == 'yield_current_frame_to_caller': + return True + return self.stackless_gc and LL_OPERATIONS[op.opname].canunwindgc def analyze_external_call(self, op): callable = op.args[0].value._obj._callable From cfbolz at codespeak.net Sat May 20 22:56:24 2006 From: cfbolz at codespeak.net (cfbolz at codespeak.net) Date: Sat, 20 May 2006 22:56:24 +0200 (CEST) Subject: [pypy-svn] r27520 - pypy/dist/pypy/translator/tool Message-ID: <20060520205624.141F210070@code0.codespeak.net> Author: cfbolz Date: Sat May 20 22:56:22 2006 New Revision: 27520 Modified: pypy/dist/pypy/translator/tool/lltracker.py Log: make the tracker not crash if one of the pointers is NULL Modified: pypy/dist/pypy/translator/tool/lltracker.py ============================================================================== --- pypy/dist/pypy/translator/tool/lltracker.py (original) +++ pypy/dist/pypy/translator/tool/lltracker.py Sat May 20 22:56:22 2006 @@ -126,8 +126,12 @@ size_gc_header = ll_object continue if isinstance(lltype.typeOf(ll_object), lltype.Ptr): - ll_object = lltype.normalizeptr(ll_object)._obj - if ll_object not in lst: + ptr = lltype.normalizeptr(ll_object) + if ptr is not None: + ll_object = ptr._obj + else: + ll_object = None + if ll_object is not None and ll_object not in lst: lst.append(ll_object) page = LLRefTrackerPage(lst, size_gc_header) if len(lst) == 2: From pedronis at codespeak.net Sun May 21 04:26:46 2006 From: pedronis at codespeak.net (pedronis at codespeak.net) Date: Sun, 21 May 2006 04:26:46 +0200 (CEST) Subject: [pypy-svn] r27521 - pypy/branch/explicit_resume_pt_experiment Message-ID: <20060521022646.C8EE210070@code0.codespeak.net> Author: pedronis Date: Sun May 21 04:26:43 2006 New Revision: 27521 Added: pypy/branch/explicit_resume_pt_experiment/ - copied from r27520, pypy/dist/pypy/ Log: making a branch to checkin my rough experiments with explicit resume points too unfinished to check it on the trunk, OTOH the first test passes on the llinterp. From pedronis at codespeak.net Sun May 21 04:36:54 2006 From: pedronis at codespeak.net (pedronis at codespeak.net) Date: Sun, 21 May 2006 04:36:54 +0200 (CEST) Subject: [pypy-svn] r27522 - in pypy/branch/explicit_resume_pt_experiment: annotation rpython rpython/lltypesystem translator/stackless translator/stackless/test Message-ID: <20060521023654.BD0E210070@code0.codespeak.net> Author: pedronis Date: Sun May 21 04:36:43 2006 New Revision: 27522 Added: pypy/branch/explicit_resume_pt_experiment/translator/stackless/test/test_resume_point.py (contents, props changed) Modified: pypy/branch/explicit_resume_pt_experiment/annotation/builtin.py pypy/branch/explicit_resume_pt_experiment/rpython/llinterp.py pypy/branch/explicit_resume_pt_experiment/rpython/lltypesystem/lloperation.py pypy/branch/explicit_resume_pt_experiment/rpython/lltypesystem/rbuiltin.py pypy/branch/explicit_resume_pt_experiment/rpython/objectmodel.py pypy/branch/explicit_resume_pt_experiment/translator/stackless/code.py pypy/branch/explicit_resume_pt_experiment/translator/stackless/transform.py Log: rough experiment on explicit resume points with stackless transformed code: primitives: resume_point(LABEL, values to restore vars, [returs=var]) resume_after(TYP, LABEL, values for var to restore [returns=value for return]) the first test in test_resume_point works on the llinterp. too unpolished/incomplete for the trunk tough. there are also some open issues. There may be oversights and some things are quite hackish: I wanted to quickly explore how hard this would be. Modified: pypy/branch/explicit_resume_pt_experiment/annotation/builtin.py ============================================================================== --- pypy/branch/explicit_resume_pt_experiment/annotation/builtin.py (original) +++ pypy/branch/explicit_resume_pt_experiment/annotation/builtin.py Sun May 21 04:36:43 2006 @@ -298,6 +298,13 @@ def robjmodel_hint(s, **kwds_s): return s +def robjmodel_resume_point(label, *args_s, **kwds_s): + return immutablevalue(None) + +def robjmodel_resume_after(s_typ, label, *args_s, **kwds_s): + assert s_typ.is_constant() + return getbookkeeper().valueoftype(s_typ.const) + def llmemory_cast_ptr_to_adr(s): return SomeAddress() @@ -357,6 +364,8 @@ BUILTIN_ANALYZERS[pypy.rpython.objectmodel.hlinvoke] = robjmodel_hlinvoke BUILTIN_ANALYZERS[pypy.rpython.objectmodel.keepalive_until_here] = robjmodel_keepalive_until_here BUILTIN_ANALYZERS[pypy.rpython.objectmodel.hint] = robjmodel_hint +BUILTIN_ANALYZERS[pypy.rpython.objectmodel.resume_point] = robjmodel_resume_point +BUILTIN_ANALYZERS[pypy.rpython.objectmodel.resume_after] = robjmodel_resume_after BUILTIN_ANALYZERS[pypy.rpython.lltypesystem.llmemory.cast_ptr_to_adr] = llmemory_cast_ptr_to_adr BUILTIN_ANALYZERS[pypy.rpython.lltypesystem.llmemory.cast_adr_to_ptr] = llmemory_cast_adr_to_ptr BUILTIN_ANALYZERS[pypy.rpython.lltypesystem.llmemory.cast_adr_to_int] = llmemory_cast_adr_to_int Modified: pypy/branch/explicit_resume_pt_experiment/rpython/llinterp.py ============================================================================== --- pypy/branch/explicit_resume_pt_experiment/rpython/llinterp.py (original) +++ pypy/branch/explicit_resume_pt_experiment/rpython/llinterp.py Sun May 21 04:36:43 2006 @@ -423,6 +423,9 @@ def op_hint(self, x, hints): return x + def op_resume_point(self, *args): + pass + def op_decode_arg(self, fname, i, name, vargs, vkwds): raise NotImplementedError("decode_arg") Modified: pypy/branch/explicit_resume_pt_experiment/rpython/lltypesystem/lloperation.py ============================================================================== --- pypy/branch/explicit_resume_pt_experiment/rpython/lltypesystem/lloperation.py (original) +++ pypy/branch/explicit_resume_pt_experiment/rpython/lltypesystem/lloperation.py Sun May 21 04:36:43 2006 @@ -343,6 +343,9 @@ 'yield_current_frame_to_caller': LLOp(canraise=(StackException,)), # can always unwind, not just if stackless gc + 'resume_point': LLOp(canraise=(StackException,)), + 'resume_after': LLOp(canraise=(Exception, StackException)), + # __________ misc operations __________ 'keepalive': LLOp(), Modified: pypy/branch/explicit_resume_pt_experiment/rpython/lltypesystem/rbuiltin.py ============================================================================== --- pypy/branch/explicit_resume_pt_experiment/rpython/lltypesystem/rbuiltin.py (original) +++ pypy/branch/explicit_resume_pt_experiment/rpython/lltypesystem/rbuiltin.py Sun May 21 04:36:43 2006 @@ -59,8 +59,46 @@ c = hop.inputconst(pyobj_repr, __import__) return hop.genop('simple_call', [c] + args_v, resulttype = pyobj_repr) +def rtype_resume_point(hop, **kwds_i): + assert hop.args_s[0].is_constant() + c_label = hop.inputconst(lltype.Void, hop.args_s[0].const) + args_v = hop.args_v[1:] + if 'i_returns' in kwds_i: + assert len(kwds_i) == 1 + returns_index = kwds_i['i_returns'] + v_return = args_v.pop(returns_index-1) + else: + assert not kwds_i + v_return = hop.inputconst(lltype.Void, None) + + hop.exception_is_here() + return hop.genop('resume_point', [c_label, v_return] + args_v, + hop.r_result) + +def rtype_resume_after(hop, **kwds_i): + # xxx hack, can do this in transform + assert hop.args_s[1].is_constant() + c_label = hop.inputconst(lltype.Void, hop.args_s[1].const) + args_v = hop.args_v[2:] + if 'i_returns' in kwds_i: + assert len(kwds_i) == 1 + returns_index = kwds_i['i_returns'] + v_return = args_v.pop(returns_index-1) + else: + assert not kwds_i + v_return = hop.inputconst(lltype.Void, None) + + from pypy.rpython.lltypesystem import llmemory + v_state = hop.genop('resume_after_prepare', [c_label] + args_v, + llmemory.GCREF) + hop.exception_is_here() + return hop.genop('resume_after', [v_state, v_return], + hop.r_result) + BUILTIN_TYPER = {} BUILTIN_TYPER[objectmodel.instantiate] = rtype_instantiate BUILTIN_TYPER[isinstance] = rtype_builtin_isinstance BUILTIN_TYPER[hasattr] = rtype_builtin_hasattr BUILTIN_TYPER[__import__] = rtype_builtin___import__ +BUILTIN_TYPER[objectmodel.resume_point] = rtype_resume_point +BUILTIN_TYPER[objectmodel.resume_after] = rtype_resume_after Modified: pypy/branch/explicit_resume_pt_experiment/rpython/objectmodel.py ============================================================================== --- pypy/branch/explicit_resume_pt_experiment/rpython/objectmodel.py (original) +++ pypy/branch/explicit_resume_pt_experiment/rpython/objectmodel.py Sun May 21 04:36:43 2006 @@ -53,6 +53,11 @@ def hint(x, **kwds): return x +def resume_point(label, *args, **kwds): + pass + +def resume_after(typ, label, *args, **kwds): + pass class FREED_OBJECT(object): def __getattribute__(self, attr): Modified: pypy/branch/explicit_resume_pt_experiment/translator/stackless/code.py ============================================================================== --- pypy/branch/explicit_resume_pt_experiment/translator/stackless/code.py (original) +++ pypy/branch/explicit_resume_pt_experiment/translator/stackless/code.py Sun May 21 04:36:43 2006 @@ -190,6 +190,48 @@ # ____________________________________________________________ +# xxx combination mess + +def resume_after_long(state, retvalue): + return 0 + +resume_after_long.stackless_explicit = True +INDEX_RESUME_AFTER_LONG = frame.RestartInfo.add_prebuilt(resume_after_long, + [EMPTY_STATE]) + +RESUME_AFTER_STATE = frame.make_state_header_type('resume_after_state', + ('c', SAVED_REFERENCE),) + +def resume_after_void(state, retvalue): + if global_state.restart_substate == -1: + # normal entry point for a call to state.switch() + # first unwind the stack + u = UnwindException() + s = lltype.malloc(RESUME_AFTER_STATE) + s.header.f_restart = INDEX_RESUME_AFTER_VOID + s.c = state + add_frame_state(u, s.header) + raise u + elif global_state.restart_substate == 0: + # STATE 0: we didn't do anything so far, but the stack is unwound + global_state.restart_substate = -1 + # grab the frame corresponding to ourself + # the 'targetstate' local is garbage here, it must be read back from + # 's.c' where we saved it by the normal entry point above + mystate = global_state.top + s = lltype.cast_pointer(lltype.Ptr(RESUME_AFTER_STATE), mystate) + targetstate = lltype.cast_opaque_ptr(lltype.Ptr(STATE_HEADER), s.c) + targetstate.f_back = mystate.f_back + global_state.top = targetstate + raise UnwindException() + else: + return 0 + +resume_after_void.stackless_explicit = True +INDEX_RESUME_AFTER_VOID = frame.RestartInfo.add_prebuilt(resume_after_void, + [RESUME_AFTER_STATE, + EMPTY_STATE]) + class StacklessData: def __init__(self): self.top = frame.null_state Added: pypy/branch/explicit_resume_pt_experiment/translator/stackless/test/test_resume_point.py ============================================================================== --- (empty file) +++ pypy/branch/explicit_resume_pt_experiment/translator/stackless/test/test_resume_point.py Sun May 21 04:36:43 2006 @@ -0,0 +1,72 @@ +from pypy.rpython.objectmodel import resume_point, resume_after +from pypy.translator.stackless.transform import StacklessTransformer +from pypy.translator.stackless.test.test_transform import llinterp_stackless_function, rtype_stackless_function, one +from pypy import conftest +import py +from pypy.rpython import rstack + +def transform_stackless_function(fn): + def wrapper(argv): + return fn() + t = rtype_stackless_function(wrapper) + st = StacklessTransformer(t, wrapper, False) + st.transform_all() + if conftest.option.view: + t.view() + +def test_no_call(): + def f(x, y): + x = x-1 + resume_point("rp0", x, y) + r = x+y + rstack.stack_unwind() + return r + def example(): + v1 = f(one(),one()+one()) + v2 = resume_after(int, "rp0", one(), one()+one()+one()) + return v1*10 + v2 + res = llinterp_stackless_function(example, assert_unwind=False) + assert res == 24 + +def test_call(): + def g(x,y): + return x*y + def f(x, y): + z = g(x,y) + resume_point("rp1", y, returns=z) + return z+y + def example(): + f(one(),one()+one()) + return 0 + transform_stackless_function(example) + +def test_call_exception_handling(): + def g(x,y): + if x == 0: + raise KeyError + return x*y + def f(x, y): + try: + z = g(x,y) + resume_point("rp1", y, returns=z) + except KeyError: + return 0 + return z+y + def example(): + f(one(),one()+one()) + return 0 + transform_stackless_function(example) + +def test_call_uncovered(): + def g(x,y): + return x*y + def f(x, y): + z = g(x,y) + resume_point("rp1", y, returns=z) + return z+y+x + def example(): + f(one(),one()+one()) + return 0 + e = py.test.raises(Exception, transform_stackless_function, example) + assert e.value.args == ('not covered needed value at resume_point',) + Modified: pypy/branch/explicit_resume_pt_experiment/translator/stackless/transform.py ============================================================================== --- pypy/branch/explicit_resume_pt_experiment/translator/stackless/transform.py (original) +++ pypy/branch/explicit_resume_pt_experiment/translator/stackless/transform.py Sun May 21 04:36:43 2006 @@ -100,6 +100,10 @@ def operation_is_true(self, op): if op.opname == 'yield_current_frame_to_caller': return True + if op.opname == 'resume_point': + return True + if op.opname.startswith('resume_after'): + return True return self.stackless_gc and LL_OPERATIONS[op.opname].canunwindgc def analyze_external_call(self, op): @@ -210,6 +214,15 @@ self.yield_current_frame_to_caller_ptr = mixlevelannotator.constfunc( code.yield_current_frame_to_caller, [], s_StatePtr) + # resume_after + self.resume_after_long_ptr = mixlevelannotator.constfunc( + code.resume_after_long, [annmodel.SomePtr(llmemory.GCREF), + annmodel.SomeInteger()], + annmodel.SomeInteger()) + self.resume_after_void_ptr = mixlevelannotator.constfunc( + code.resume_after_void, [annmodel.SomePtr(llmemory.GCREF), + annmodel.s_None], + annmodel.SomeInteger()) mixlevelannotator.finish() @@ -232,6 +245,10 @@ self.reccopyannotator = MixLevelHelperAnnotator(translator.rtyper) + self.explicit_resume_points = {} + + self.explicit_resume_after = [] + # register the prebuilt restartinfos for restartinfo in frame.RestartInfo.prebuilt: self.register_restart_info(restartinfo) @@ -407,9 +424,75 @@ if op.opname == 'yield_current_frame_to_caller': op = replace_with_call(self.yield_current_frame_to_caller_ptr) stackless_op = True + if op.opname == 'resume_after': # xxx + if op.result.concretetype != lltype.Signed: + raise NotImplementedError + v_returns = op.args[1] + if v_returns.concretetype == lltype.Signed: + raise NotImplementedError + elif v_returns.concretetype == lltype.Void: + args = [self.resume_after_void_ptr] + op.args + newop = model.SpaceOperation('direct_call', args, op.result) + block.operations[i] = newop + else: + raise NotImplementedError + stackeless_op = True if (op.opname in ('direct_call', 'indirect_call') or self.analyzer.operation_is_true(op)): + # XXX special casing with duplication for now + if op.opname == 'resume_point': + if i == len(block.operations) - 1: + link = block.exits[0] + else: + link = support.split_block_with_keepalive(block, i+1) + parms = op.args[1:] + if not isinstance(parms[0], model.Variable): + assert parms[0].value is None + parms[0] = None + + args = [] + for l in block.exits: + for arg in l.args: + if isinstance(arg, model.Variable) \ + and arg.concretetype is not lltype.Void \ + and arg is not op.result \ + and arg not in args \ + and arg not in [l.last_exception, l.last_exc_value]: + args.append(arg) + if arg not in parms: + raise Exception, "not covered needed value at resume_point" + if parms[0] is not None: # returns= case + res = parms[0] + args = [arg for arg in args if arg is not res] + else: + args = args + res = op.result + + (frame_type, + fieldnames) = self.frametyper.frame_type_for_vars(args) + + self.resume_points.append( + ResumePoint(res, args, tuple(block.exits), + frame_type, fieldnames)) + + field2parm = {} + for arg, fieldname in zip(args, fieldnames): + p = parms.index(arg) + field2parm[fieldname] = p-1 # ignore parm[0] + + label = op.args[0].value + self.explicit_resume_points[label] = { + 'restart': len(self.masterarray1) + len(self.resume_points)-1, + 'frame_type': frame_type, + 'restype': res.concretetype, + 'field2parm': field2parm, + } + block = link.target + i = 0 + continue + + # trap calls to stackless-related suggested primitives if op.opname == 'direct_call': func = getattr(op.args[0].value._obj, '_callable', None) @@ -487,6 +570,9 @@ block.recloseblock(*newexits) self.translator.rtyper._convert_link(block, newlink) + if op.opname == "resume_after_prepare": + self.explicit_resume_after.append((block, i)) + block = link.target i = 0 else: @@ -594,6 +680,34 @@ # (shorter, though) ll_global_state = self.ll_global_state.value ll_global_state.inst_masterarray = masterarray + + # XXX when to do this properly with genc is a bit open + # xxx attach exception handling properly to malloc + for block, i in self.explicit_resume_after: + assert len(block.operations) == i+1 + op = block.operations[i] + llops = LowLevelOpList() + label = op.args[0].value + data = self.explicit_resume_points[label] + FRAME = data['frame_type'] + c_FRAME = model.Constant(FRAME, lltype.Void) + v_state = llops.genop('malloc', [c_FRAME], + resulttype = lltype.Ptr(FRAME)) + for fieldname, p in data['field2parm'].items(): + llops.genop('setfield', [v_state, + model.Constant(fieldname, lltype.Void), + op.args[1+p]]) + v_state = llops.genop('cast_pointer', [v_state], + resulttype = lltype.Ptr(frame.STATE_HEADER)) + llops.genop('setfield', [v_state, + model.Constant('f_restart', lltype.Void), + model.Constant(data['restart'], lltype.Signed)]) + v_state = llops.genop('cast_opaque_ptr', [v_state], + resulttype = llmemory.GCREF) + llops.append(model.SpaceOperation('same_as', [v_state], op.result)) + block.operations = block.operations[:-1] + llops + + return [masterarray] def transform_gc_nocollect(self, graph): From arigo at codespeak.net Sun May 21 10:14:51 2006 From: arigo at codespeak.net (arigo at codespeak.net) Date: Sun, 21 May 2006 10:14:51 +0200 (CEST) Subject: [pypy-svn] r27523 - in pypy/dist/pypy: rpython rpython/module translator/stackless translator/stackless/test Message-ID: <20060521081451.728681006E@code0.codespeak.net> Author: arigo Date: Sun May 21 10:14:47 2006 New Revision: 27523 Modified: pypy/dist/pypy/rpython/extfunctable.py pypy/dist/pypy/rpython/module/ll_stackless.py pypy/dist/pypy/rpython/rstack.py pypy/dist/pypy/translator/stackless/code.py pypy/dist/pypy/translator/stackless/frame.py pypy/dist/pypy/translator/stackless/test/test_clone.py pypy/dist/pypy/translator/stackless/transform.py Log: Remove the reccopy() of frames, made obsolete by the gc_x_clone() approach. Modified: pypy/dist/pypy/rpython/extfunctable.py ============================================================================== --- pypy/dist/pypy/rpython/extfunctable.py (original) +++ pypy/dist/pypy/rpython/extfunctable.py Sun May 21 10:14:47 2006 @@ -254,9 +254,7 @@ declare(rstack.stack_capture, rstack.frame_stack_top, 'll_stack/capture') frametop_type_info = declaregcptrtype(rstack.frame_stack_top,'frame_stack_top', switch = (rstack.frame_stack_top, - 'll_stackless/switch'), - clone = (rstack.frame_stack_top, - 'll_stackless/clone')) + 'll_stackless/switch')) # ___________________________________________________________ # javascript Modified: pypy/dist/pypy/rpython/module/ll_stackless.py ============================================================================== --- pypy/dist/pypy/rpython/module/ll_stackless.py (original) +++ pypy/dist/pypy/rpython/module/ll_stackless.py Sun May 21 10:14:47 2006 @@ -18,10 +18,3 @@ else: return to_opaque_object(newframetop) ll_stackless_switch.suggested_primitive = True - - -def ll_stackless_clone(opaqueframetop): - frametop = from_opaque_object(opaqueframetop) - newframetop = frametop.clone() - return to_opaque_object(newframetop) -ll_stackless_clone.suggested_primitive = True Modified: pypy/dist/pypy/rpython/rstack.py ============================================================================== --- pypy/dist/pypy/rpython/rstack.py (original) +++ pypy/dist/pypy/rpython/rstack.py Sun May 21 10:14:47 2006 @@ -32,5 +32,3 @@ class frame_stack_top(object): def switch(self): raise NotImplementedError("only works in translated versions") - def clone(self): - raise NotImplementedError("only works in translated versions") Modified: pypy/dist/pypy/translator/stackless/code.py ============================================================================== --- pypy/dist/pypy/translator/stackless/code.py (original) +++ pypy/dist/pypy/translator/stackless/code.py Sun May 21 10:14:47 2006 @@ -55,13 +55,6 @@ # ____________________________________________________________ -def ll_frame_clone(oldstate): - oldframe = lltype.cast_opaque_ptr(lltype.Ptr(STATE_HEADER), oldstate) - newframe = frame.ll_frame_reccopy(oldframe) - return lltype.cast_opaque_ptr(frame.OPAQUE_STATE_HEADER_PTR, newframe) - -# ____________________________________________________________ - def yield_current_frame_to_caller(): if global_state.restart_substate == -1: # normal entry point for yield_current_frame_to_caller() Modified: pypy/dist/pypy/translator/stackless/frame.py ============================================================================== --- pypy/dist/pypy/translator/stackless/frame.py (original) +++ pypy/dist/pypy/translator/stackless/frame.py Sun May 21 10:14:47 2006 @@ -63,44 +63,17 @@ def make_state_header_type(name, *fields): - fnname = 'll_reccopy_%s' % (name,) - source = ['def %s(frame):' % (fnname,), - ' frame = lltype.cast_pointer(lltype.Ptr(FRAME), frame)', - ' newframe = lltype.malloc(FRAME)', - ' if frame.header.f_back:', - ' newframe.header.f_back = ll_frame_reccopy(', - ' frame.header.f_back)', - ' newframe.header.f_restart = frame.header.f_restart'] - for name, _ in fields: - source.append(' newframe.%s = frame.%s' % (name, name)) - source.append(' return lltype.cast_pointer(lltype.Ptr(STATE_HEADER),') - source.append(' newframe)') - source.append('') - miniglobals = {'lltype': lltype, - 'll_frame_reccopy': ll_frame_reccopy, - 'STATE_HEADER': STATE_HEADER, - } - exec compile2('\n'.join(source)) in miniglobals - extras = { - 'adtmeths': {'reccopy': miniglobals[fnname]} - } - FRAME = lltype.GcStruct(name, - ('header', STATE_HEADER), - *fields, **extras) - miniglobals['FRAME'] = FRAME - return FRAME + return lltype.GcStruct(name, + ('header', STATE_HEADER), + *fields) # ____________________________________________________________ # master array giving information about the restart points # (STATE_HEADER.frameinfo is an index into this array) -RECCOPY_FUNC = lltype.FuncType([lltype.Ptr(STATE_HEADER)], - lltype.Ptr(STATE_HEADER)) - FRAME_INFO = lltype.Struct('frame_info', ('fnaddr', llmemory.Address), - ('info', lltype.Signed), - ('reccopy', lltype.Ptr(RECCOPY_FUNC))) + ('info', lltype.Signed)) FRAME_INFO_ARRAY = lltype.Array(FRAME_INFO) def decodestate(index): @@ -117,12 +90,6 @@ finfo.info) # retval_type decodestate.stackless_explicit = True -def ll_frame_reccopy(frame): - from pypy.translator.stackless.code import global_state - masterarray = global_state.masterarray - finfo = masterarray[frame.f_restart] - return finfo.reccopy(frame) - class RestartInfo(object): @@ -130,7 +97,7 @@ self.func_or_graph = func_or_graph self.frame_types = frame_types - def compress(self, rtyper, mix): + def compress(self, rtyper): if self.frame_types: bk = rtyper.annotator.bookkeeper graph = self.func_or_graph @@ -145,12 +112,6 @@ ] for i in range(1, len(self.frame_types)): result.append({'info': i}) - for i in range(len(self.frame_types)): - reccopy = self.frame_types[i].reccopy - s_header = annmodel.SomePtr(lltype.Ptr(STATE_HEADER)) - fnptr = mix.delayedfunction(reccopy, [s_header], - s_header) - result[i]['reccopy'] = fnptr else: result = [] return result Modified: pypy/dist/pypy/translator/stackless/test/test_clone.py ============================================================================== --- pypy/dist/pypy/translator/stackless/test/test_clone.py (original) +++ pypy/dist/pypy/translator/stackless/test/test_clone.py Sun May 21 10:14:47 2006 @@ -4,6 +4,7 @@ def test_simple(): + import py; py.test.skip("to be rewritten with gc_x_clone") def g(lst): lst.append(1) parent = rstack.yield_current_frame_to_caller() Modified: pypy/dist/pypy/translator/stackless/transform.py ============================================================================== --- pypy/dist/pypy/translator/stackless/transform.py (original) +++ pypy/dist/pypy/translator/stackless/transform.py Sun May 21 10:14:47 2006 @@ -197,9 +197,6 @@ ll_stackless.ll_stackless_switch: mixlevelannotator.constfunc( code.ll_frame_switch, [s_StatePtr], s_StatePtr), - ll_stackless.ll_stackless_clone: - mixlevelannotator.constfunc( - code.ll_frame_clone, [s_StatePtr], s_StatePtr), ll_stack.ll_stack_unwind: mixlevelannotator.constfunc( code.ll_stack_unwind, [], annmodel.s_None), @@ -230,8 +227,6 @@ lltype.typeOf(null_state)) self.c_gc_nocollect = model.Constant("gc_nocollect", lltype.Void) - self.reccopyannotator = MixLevelHelperAnnotator(translator.rtyper) - # register the prebuilt restartinfos for restartinfo in frame.RestartInfo.prebuilt: self.register_restart_info(restartinfo) @@ -577,13 +572,12 @@ def register_restart_info(self, restartinfo): rtyper = self.translator.rtyper - for frame_info_dict in restartinfo.compress(rtyper, self.reccopyannotator): + for frame_info_dict in restartinfo.compress(rtyper): self.masterarray1.append(frame_info_dict) def finish(self): # compute the final masterarray by copying over the masterarray1, # which is a list of dicts of attributes - self.reccopyannotator.finish() masterarray = lltype.malloc(frame.FRAME_INFO_ARRAY, len(self.masterarray1), immortal=True) From arigo at codespeak.net Sun May 21 10:16:09 2006 From: arigo at codespeak.net (arigo at codespeak.net) Date: Sun, 21 May 2006 10:16:09 +0200 (CEST) Subject: [pypy-svn] r27524 - pypy/dist/pypy/rpython Message-ID: <20060521081609.D9A451006E@code0.codespeak.net> Author: arigo Date: Sun May 21 10:16:08 2006 New Revision: 27524 Modified: pypy/dist/pypy/rpython/rtyper.py Log: * Possibly fixed the problem of specialize_more_blocks() being slow when called repeatedly. * Print nevertheless a line of information every time it has been called. Modified: pypy/dist/pypy/rpython/rtyper.py ============================================================================== --- pypy/dist/pypy/rpython/rtyper.py (original) +++ pypy/dist/pypy/rpython/rtyper.py Sun May 21 10:16:08 2006 @@ -66,6 +66,7 @@ self.cache_dummy_values = {} self.typererrors = [] self.typererror_count = 0 + self.seen_graphs_count = 0 # make the primitive_to_repr constant mapping self.primitive_to_repr = {} if self.type_system.offers_exceptiondata: @@ -179,6 +180,11 @@ self.list_of_str_repr = self.getrepr(annmodel.SomeList(ldef)) def specialize_more_blocks(self): + if self.already_seen: + newtext = ' more' + else: + newtext = '' + blockcount = 0 while True: # look for blocks not specialized yet pending = [block for block in self.annotator.annotated @@ -199,6 +205,7 @@ # specialize all blocks in the 'pending' list for block in pending: tracking(block) + blockcount += 1 self.specialize_block(block) self.already_seen[block] = True # progress bar @@ -218,9 +225,12 @@ self.dump_typererrors(to_log=True) raise TyperError("there were %d error" % len(self.typererrors)) # make sure that the return variables of all graphs are concretetype'd - for graph in self.annotator.translator.graphs: + newgraphs = self.annotator.translator.graphs[self.seen_graphs_count:] + self.seen_graphs_count += len(newgraphs) + for graph in newgraphs: v = graph.getreturnvar() self.setconcretetype(v) + log.event('-=- specialized %d%s blocks -=-' % (blockcount, newtext)) def dump_typererrors(self, num=None, minimize=True, to_log=False): c = 0 @@ -441,7 +451,7 @@ yield HighLevelOp(self, block.operations[-1], exclinks, llops) def translate_hl_to_ll(self, hop, varmapping): - log.translating(hop.spaceop.opname, hop.args_s) + #log.translating(hop.spaceop.opname, hop.args_s) resultvar = hop.dispatch() if hop.exceptionlinks and hop.llops.llop_raising_exceptions is None: raise TyperError("the graph catches %s, but the rtyper did not " From cfbolz at codespeak.net Sun May 21 11:01:42 2006 From: cfbolz at codespeak.net (cfbolz at codespeak.net) Date: Sun, 21 May 2006 11:01:42 +0200 (CEST) Subject: [pypy-svn] r27525 - in pypy/dist/pypy/rpython/memory: . test Message-ID: <20060521090142.103621006E@code0.codespeak.net> Author: cfbolz Date: Sun May 21 11:01:39 2006 New Revision: 27525 Modified: pypy/dist/pypy/rpython/memory/gc.py pypy/dist/pypy/rpython/memory/gctransform.py pypy/dist/pypy/rpython/memory/gcwrapper.py pypy/dist/pypy/rpython/memory/test/test_transformed_gc.py Log: first cut at implementing __del__ for the mark and sweep collector Modified: pypy/dist/pypy/rpython/memory/gc.py ============================================================================== --- pypy/dist/pypy/rpython/memory/gc.py (original) +++ pypy/dist/pypy/rpython/memory/gc.py Sun May 21 11:01:39 2006 @@ -60,11 +60,13 @@ class GCBase(object): _alloc_flavor_ = "raw" - def set_query_functions(self, is_varsize, offsets_to_gc_pointers, + def set_query_functions(self, is_varsize, getfinalizer, + offsets_to_gc_pointers, fixed_size, varsize_item_sizes, varsize_offset_to_variable_part, varsize_offset_to_length, varsize_offsets_to_gcpointers_in_var_part): + self.getfinalizer = getfinalizer self.is_varsize = is_varsize self.offsets_to_gc_pointers = offsets_to_gc_pointers self.fixed_size = fixed_size @@ -133,8 +135,8 @@ self.bytes_malloced_threshold = start_heap_size self.total_collection_time = 0.0 self.AddressLinkedList = AddressLinkedList - #self.set_query_functions(None, None, None, None, None, None, None) self.malloced_objects = lltype.nullptr(self.HDR) + self.malloced_objects_with_finalizer = lltype.nullptr(self.HDR) self.get_roots = get_roots self.gcheaderbuilder = GCHeaderBuilder(self.HDR) # pools, for x_swap_pool(): @@ -172,8 +174,12 @@ result = raw_malloc(size_gc_header + size) hdr = llmemory.cast_adr_to_ptr(result, self.HDRPTR) hdr.typeid = typeid << 1 - hdr.next = self.malloced_objects - self.malloced_objects = hdr + if not self.getfinalizer(typeid): + hdr.next = self.malloced_objects + self.malloced_objects = hdr + else: + hdr.next = self.malloced_objects_with_finalizer + self.malloced_objects_with_finalizer = hdr self.bytes_malloced += raw_malloc_usage(size + size_gc_header) result += size_gc_header return llmemory.cast_adr_to_ptr(result, llmemory.GCREF) @@ -193,14 +199,24 @@ (result + size_gc_header + offset_to_length).signed[0] = length hdr = llmemory.cast_adr_to_ptr(result, self.HDRPTR) hdr.typeid = typeid << 1 - hdr.next = self.malloced_objects - self.malloced_objects = hdr + if not self.getfinalizer(typeid): + hdr.next = self.malloced_objects + self.malloced_objects = hdr + else: + hdr.next = self.malloced_objects_with_finalizer + self.malloced_objects_with_finalizer = hdr self.bytes_malloced += raw_malloc_usage(size + size_gc_header) result += size_gc_header return llmemory.cast_adr_to_ptr(result, llmemory.GCREF) def collect(self): + # 1. mark from the roots, and also the objects that objects-with-del + # point to (using the list of malloced_objects_with_finalizer) + # 2. walk the list of objects-without-del and free the ones not marked + # 3. walk the list of objects-with-del and for the ones not marked: + # call __del__, move the object to the list of object-without-del import time + from pypy.rpython.lltypesystem.lloperation import llop if DEBUG_PRINT: llop.debug_print(lltype.Void, 'collecting...') start_time = time.time() @@ -208,10 +224,11 @@ size_gc_header = self.gcheaderbuilder.size_gc_header ## llop.debug_view(lltype.Void, self.malloced_objects, self.poolnodes, ## size_gc_header) - objects = self.AddressLinkedList() + + # push the roots on the mark stack + objects = self.AddressLinkedList() # mark stack while 1: curr = roots.pop() -## print "root: ", curr if curr == NULL: break # roots is a list of addresses to addresses: @@ -225,35 +242,37 @@ # from this point onwards, no more mallocs should be possible old_malloced = self.bytes_malloced self.bytes_malloced = 0 + curr_heap_size = 0 + freed_size = 0 + + # mark objects reachable by objects with a finalizer, but not those + # themselves. add their size to curr_heap_size, since they always + # survive the collection + hdr = self.malloced_objects_with_finalizer + while hdr: + next = hdr.next + typeid = hdr.typeid >> 1 + gc_info = llmemory.cast_ptr_to_adr(hdr) + obj = gc_info + size_gc_header + self.add_reachable_to_stack(obj, objects) + addr = llmemory.cast_ptr_to_adr(hdr) + size = self.fixed_size(typeid) + if self.is_varsize(typeid): + length = (obj + self.varsize_offset_to_length(typeid)).signed[0] + size += self.varsize_item_sizes(typeid) * length + estimate = raw_malloc_usage(size_gc_header + size) + curr_heap_size += estimate + hdr = next + + # mark thinks on the mark stack and put their descendants onto the + # stack until the stack is empty while objects.non_empty(): #mark curr = objects.pop() -## print "object: ", curr + self.add_reachable_to_stack(curr, objects) gc_info = curr - size_gc_header hdr = llmemory.cast_adr_to_ptr(gc_info, self.HDRPTR) if hdr.typeid & 1: continue - typeid = hdr.typeid >> 1 - offsets = self.offsets_to_gc_pointers(typeid) - i = 0 - while i < len(offsets): - pointer = curr + offsets[i] - objects.append(pointer.address[0]) - i += 1 - if self.is_varsize(typeid): - offset = self.varsize_offset_to_variable_part( - typeid) - length = (curr + self.varsize_offset_to_length(typeid)).signed[0] - curr += offset - offsets = self.varsize_offsets_to_gcpointers_in_var_part(typeid) - itemlength = self.varsize_item_sizes(typeid) - i = 0 - while i < length: - item = curr + itemlength * i - j = 0 - while j < len(offsets): - objects.append((item + offsets[j]).address[0]) - j += 1 - i += 1 hdr.typeid = hdr.typeid | 1 objects.delete() # also mark self.curpool @@ -262,8 +281,8 @@ hdr = llmemory.cast_adr_to_ptr(gc_info, self.HDRPTR) hdr.typeid = hdr.typeid | 1 - curr_heap_size = 0 - freed_size = 0 + # sweep: delete objects without del if they are not marked + # unmark objects without del that are marked firstpoolnode = lltype.malloc(self.POOLNODE, flavor='raw') firstpoolnode.linkedlist = self.malloced_objects firstpoolnode.nextnode = self.poolnodes @@ -328,10 +347,56 @@ ## llop.debug_view(lltype.Void, self.malloced_objects, self.poolnodes, ## size_gc_header) assert self.heap_usage + old_malloced == curr_heap_size + freed_size + + # call finalizers if needed self.heap_usage = curr_heap_size + hdr = self.malloced_objects_with_finalizer + self.malloced_objects_with_finalizer = lltype.nullptr(self.HDR) + while hdr: + next = hdr.next + if hdr.typeid & 1: + hdr.next = self.malloced_objects_with_finalizer + self.malloced_objects_with_finalizer = hdr + hdr.typeid = hdr.typeid & (~1) + else: + obj = llmemory.cast_ptr_to_adr(hdr) + size_gc_header + finalizer = self.getfinalizer(hdr.typeid >> 1) + finalizer(obj) + hdr.next = self.malloced_objects + self.malloced_objects = hdr + hdr = next STATISTICS_NUMBERS = 2 + def add_reachable_to_stack(self, obj, objects): + size_gc_header = self.gcheaderbuilder.size_gc_header + gc_info = obj - size_gc_header + hdr = llmemory.cast_adr_to_ptr(gc_info, self.HDRPTR) + if hdr.typeid & 1: + return + typeid = hdr.typeid >> 1 + offsets = self.offsets_to_gc_pointers(typeid) + i = 0 + while i < len(offsets): + pointer = obj + offsets[i] + objects.append(pointer.address[0]) + i += 1 + if self.is_varsize(typeid): + offset = self.varsize_offset_to_variable_part( + typeid) + length = (obj + self.varsize_offset_to_length(typeid)).signed[0] + obj += offset + offsets = self.varsize_offsets_to_gcpointers_in_var_part(typeid) + itemlength = self.varsize_item_sizes(typeid) + i = 0 + while i < length: + item = obj + itemlength * i + j = 0 + while j < len(offsets): + objects.append((item + offsets[j]).address[0]) + j += 1 + i += 1 + def statistics(self): return self.heap_usage, self.bytes_malloced Modified: pypy/dist/pypy/rpython/memory/gctransform.py ============================================================================== --- pypy/dist/pypy/rpython/memory/gctransform.py (original) +++ pypy/dist/pypy/rpython/memory/gctransform.py Sun May 21 11:01:39 2006 @@ -388,6 +388,16 @@ ADDRESS_VOID_FUNC = lltype.FuncType([llmemory.Address], lltype.Void) +def get_rtti(TYPE): + if isinstance(TYPE, lltype.GcStruct): + try: + return lltype.getRuntimeTypeInfo(TYPE) + except ValueError: + pass + return None + + + class RefcountingGCTransformer(GCTransformer): HDR = lltype.Struct("header", ("refcount", lltype.Signed)) @@ -483,14 +493,6 @@ result.extend(self.pop_alive(oldval)) return result - def get_rtti(self, TYPE): - if isinstance(TYPE, lltype.GcStruct): - try: - return lltype.getRuntimeTypeInfo(TYPE) - except ValueError: - pass - return None - def finish(self): super(RefcountingGCTransformer, self).finish() @@ -506,7 +508,7 @@ return self.static_deallocator_funcptrs[TYPE] #print_call_chain(self) - rtti = self.get_rtti(TYPE) + rtti = get_rtti(TYPE) if rtti is not None and hasattr(rtti._obj, 'destructor_funcptr'): destrptr = rtti._obj.destructor_funcptr DESTR_ARG = lltype.typeOf(destrptr).TO.ARGS[0] @@ -576,7 +578,7 @@ return self.dynamic_deallocator_funcptrs[TYPE] #print_call_chain(self) - rtti = self.get_rtti(TYPE) + rtti = get_rtti(TYPE) if rtti is None: p = self.static_deallocation_funcptr_for_type(TYPE) self.dynamic_deallocator_funcptrs[TYPE] = p @@ -661,14 +663,6 @@ """ for boehm it is enough to do nothing""" return [SpaceOperation("same_as", [Constant(None, lltype.Void)], op.result)] - def get_rtti(self, TYPE): - if isinstance(TYPE, lltype.GcStruct): - try: - return lltype.getRuntimeTypeInfo(TYPE) - except ValueError: - pass - return None - def finish(self): super(BoehmGCTransformer, self).finish() @@ -676,7 +670,7 @@ if TYPE in self.finalizer_funcptrs: return self.finalizer_funcptrs[TYPE] - rtti = self.get_rtti(TYPE) + rtti = get_rtti(TYPE) if rtti is not None and hasattr(rtti._obj, 'destructor_funcptr'): destrptr = rtti._obj.destructor_funcptr DESTR_ARG = lltype.typeOf(destrptr).TO.ARGS[0] @@ -751,11 +745,14 @@ super(FrameworkGCTransformer, self).__init__(translator, inline=True) AddressLinkedList = get_address_linked_list() GCClass = self.GCClass + self.finalizer_funcptrs = {} + self.FINALIZERTYPE = lltype.Ptr(ADDRESS_VOID_FUNC) class GCData(object): # types of the GC information tables OFFSETS_TO_GC_PTR = lltype.Array(lltype.Signed) TYPE_INFO = lltype.Struct("type_info", ("isvarsize", lltype.Bool), + ("finalyzer", self.FINALIZERTYPE), ("fixedsize", lltype.Signed), ("ofstoptrs", lltype.Ptr(OFFSETS_TO_GC_PTR)), ("varitemsize", lltype.Signed), @@ -768,6 +765,9 @@ def q_is_varsize(typeid): return gcdata.type_info_table[typeid].isvarsize + def q_finalyzer(typeid): + return gcdata.type_info_table[typeid].finalyzer + def q_offsets_to_gc_pointers(typeid): return gcdata.type_info_table[typeid].ofstoptrs @@ -818,6 +818,7 @@ gcdata.gc.setup() gcdata.gc.set_query_functions( q_is_varsize, + q_finalyzer, q_offsets_to_gc_pointers, q_fixed_size, q_varsize_item_sizes, @@ -984,6 +985,7 @@ self.id_of_type[TYPE] = type_id offsets = offsets_to_gc_pointers(TYPE) info["ofstoptrs"] = self.offsets2table(offsets, TYPE) + info["finalyzer"] = self.finalizer_funcptr_for_type(TYPE) if not TYPE._is_varsize(): info["isvarsize"] = False info["fixedsize"] = llmemory.sizeof(TYPE) @@ -1018,6 +1020,31 @@ info["varitemsize"] = 0 return type_id + def finalizer_funcptr_for_type(self, TYPE): + if TYPE in self.finalizer_funcptrs: + return self.finalizer_funcptrs[TYPE] + + rtti = get_rtti(TYPE) + if rtti is not None and hasattr(rtti._obj, 'destructor_funcptr'): + destrptr = rtti._obj.destructor_funcptr + DESTR_ARG = lltype.typeOf(destrptr).TO.ARGS[0] + else: + destrptr = None + DESTR_ARG = None + + assert not type_contains_pyobjs(TYPE), "not implemented" + if destrptr: + def ll_finalizer(addr): + v = llmemory.cast_adr_to_ptr(addr, DESTR_ARG) + ll_call_destructor(destrptr, v) + g, fptr = self.annotate_helper(ll_finalizer, [llmemory.Address], lltype.Void) + else: + g = fptr = lltype.nullptr(ADDRESS_VOID_FUNC) + if g: + self.need_minimal_transform(g) + self.finalizer_funcptrs[TYPE] = fptr + return fptr + def consider_constant(self, TYPE, value): if id(value) in self.seen_roots: return Modified: pypy/dist/pypy/rpython/memory/gcwrapper.py ============================================================================== --- pypy/dist/pypy/rpython/memory/gcwrapper.py (original) +++ pypy/dist/pypy/rpython/memory/gcwrapper.py Sun May 21 11:01:39 2006 @@ -27,6 +27,7 @@ def create_query_functions(self): from pypy.rpython.lltypesystem import rstr _is_varsize = [] + _finalizers = [] _offsets_to_gc_pointers = [] _fixed_size = [] _varsize_item_sizes = [] @@ -39,6 +40,7 @@ for TYPE, typeid in tttid: varsize = self.is_varsize(typeid) _is_varsize.append(varsize) + _finalizers.append(None) _offsets_to_gc_pointers.append(self.offsets_to_gc_pointers(typeid)) _fixed_size.append(self.fixed_size(typeid)) if varsize: @@ -54,8 +56,12 @@ _varsize_offset_to_variable_part.append(0) _varsize_offset_to_length.append(0) _varsize_offsets_to_gcpointers_in_var_part.append([]) + # trick to make the annotator see that the list can contain functions: + _finalizers.append(lambda addr: None) def is_varsize(typeid): return _is_varsize[typeid] + def getfinalizer(typeid): + return _finalizers[typeid] def offsets_to_gc_pointers(typeid): return _offsets_to_gc_pointers[typeid] def fixed_size(typeid): @@ -68,7 +74,7 @@ return _varsize_offset_to_length[typeid] def varsize_offsets_to_gcpointers_in_var_part(typeid): return _varsize_offsets_to_gcpointers_in_var_part[typeid] - return (is_varsize, offsets_to_gc_pointers, fixed_size, + return (is_varsize, getfinalizer, offsets_to_gc_pointers, fixed_size, varsize_item_sizes, varsize_offset_to_variable_part, varsize_offset_to_length, varsize_offsets_to_gcpointers_in_var_part) @@ -80,6 +86,9 @@ (isinstance(TYPE, lltype.Struct) and TYPE._arrayfld is not None)) + def getfinalizer(self, typeid): + return None + def offsets_to_gc_pointers(self, typeid): assert typeid >= 0 return lltypelayout.offsets_to_gc_pointers(self.types[typeid]) @@ -118,51 +127,12 @@ return 0 def get_setup_query_functions(self): - return (self.is_varsize, self.offsets_to_gc_pointers, self.fixed_size, + return (self.is_varsize, self.getfinalizer, + self.offsets_to_gc_pointers, self.fixed_size, self.varsize_item_sizes, self.varsize_offset_to_variable_part, self.varsize_offset_to_length, self.varsize_offsets_to_gcpointers_in_var_part) -class SymbolicQueryTypes(QueryTypes): - def fixed_size(self, typeid): - assert typeid >= 0 - if self.types[typeid]._is_varsize(): - return llmemory.sizeof(self.types[typeid], 0) - else: - return llmemory.sizeof(self.types[typeid]) - - def varsize_item_sizes(self, typeid): - assert typeid >= 0 - if self.is_varsize(typeid): - return llmemory.ItemOffset(self.types[typeid]) - else: - return 0 - - def varsize_offset_to_variable_part(self, typeid): - assert typeid >= 0 - if self.is_varsize(typeid): - return llmemory.ArrayItemsOffset(self.types[typeid]) - else: - return 0 - - def varsize_offset_to_length(self, typeid): - assert typeid >= 0 - if self.is_varsize(typeid): - TYPE = self.types[typeid] - if isinstance(TYPE, lltype.Array): - return 0 - else: - return llmemory.FieldOffset(TYPE, TYPE._arrayfld) - else: - return 0 - - def varsize_offsets_to_gcpointers_in_var_part(self, typeid): - assert typeid >= 0 - if self.is_varsize(typeid): - return lltypelayout.varsize_offsets_to_gcpointers_in_var_part( - self.types[typeid]) - else: - return 0 def getfunctionptr(annotator, graphfunc): """Make a functionptr from the given Python function.""" @@ -276,10 +246,10 @@ AddressLinkedList = self.AddressLinkedList def instantiate_linked_list(): return AddressLinkedList() - f1, f2, f3, f4, f5, f6, f7 = self.query_types.create_query_functions() + f1, f2, f3, f4, f5, f6, f7, f8 = self.query_types.create_query_functions() the_gc = gc_class(AddressLinkedList) def instantiate_gc(): - the_gc.set_query_functions(f1, f2, f3, f4, f5, f6, f7) + the_gc.set_query_functions(f1, f2, f3, f4, f5, f6, f7, f8) the_gc.setup() return the_gc func, dummy_get_roots1, dummy_get_roots2 = gc.get_dummy_annotate( Modified: pypy/dist/pypy/rpython/memory/test/test_transformed_gc.py ============================================================================== --- pypy/dist/pypy/rpython/memory/test/test_transformed_gc.py (original) +++ pypy/dist/pypy/rpython/memory/test/test_transformed_gc.py Sun May 21 11:01:39 2006 @@ -293,6 +293,61 @@ heap_size = statistics().item0 assert heap_size < 16000 * INT_SIZE / 4 # xxx + def test_finalizer(self): + class B(object): + pass + b = B() + b.nextid = 0 + b.num_deleted = 0 + class A(object): + def __init__(self): + self.id = b.nextid + b.nextid += 1 + def __del__(self): + b.num_deleted += 1 + def f(x, y): + a = A() + i = 0 + while i < x: + i += 1 + a = A() + llop.gc__collect(lltype.Void) + llop.gc__collect(lltype.Void) + return b.num_deleted + run = self.runner(f, nbargs=2) + res = run([5, 42]) #XXX pure lazyness here too + assert res == 6 + + def test_finalizer_calls_malloc(self): + class B(object): + pass + b = B() + b.nextid = 0 + b.num_deleted = 0 + class A(object): + def __init__(self): + self.id = b.nextid + b.nextid += 1 + def __del__(self): + b.num_deleted += 1 + C() + class C(A): + def __del__(self): + b.num_deleted += 1 + def f(x, y): + a = A() + c = C() + i = 0 + while i < x: + i += 1 + a = A() + llop.gc__collect(lltype.Void) + llop.gc__collect(lltype.Void) + return b.num_deleted + run = self.runner(f, nbargs=2) + res = run([5, 42]) #XXX pure lazyness here too + assert res == 13 + def test_cloning(self): B = lltype.GcStruct('B', ('x', lltype.Signed)) A = lltype.GcStruct('A', ('b', lltype.Ptr(B)), From arigo at codespeak.net Sun May 21 11:06:52 2006 From: arigo at codespeak.net (arigo at codespeak.net) Date: Sun, 21 May 2006 11:06:52 +0200 (CEST) Subject: [pypy-svn] r27526 - in pypy/dist/pypy: jit/timeshifter rpython/lltypesystem rpython/ootypesystem Message-ID: <20060521090652.8D4D310061@code0.codespeak.net> Author: arigo Date: Sun May 21 11:06:50 2006 New Revision: 27526 Modified: pypy/dist/pypy/jit/timeshifter/timeshift.py pypy/dist/pypy/rpython/lltypesystem/rtuple.py pypy/dist/pypy/rpython/ootypesystem/rtuple.py Log: Added a global 'newtuple' in rtuple, which is more natural for calls from outside the rtyper. Modified: pypy/dist/pypy/jit/timeshifter/timeshift.py ============================================================================== --- pypy/dist/pypy/jit/timeshifter/timeshift.py (original) +++ pypy/dist/pypy/jit/timeshifter/timeshift.py Sun May 21 11:06:50 2006 @@ -324,7 +324,7 @@ s_key_tuple = annmodel.SomeTuple(items_s) r_key = getrepr(s_key_tuple) r_key.setup() - v_key = rtuple.TupleRepr.newtuple(llops, r_key, key_v) + v_key = rtuple.newtuple(llops, r_key, key_v) v_oldjitstate = newinputargs[0] Modified: pypy/dist/pypy/rpython/lltypesystem/rtuple.py ============================================================================== --- pypy/dist/pypy/rpython/lltypesystem/rtuple.py (original) +++ pypy/dist/pypy/rpython/lltypesystem/rtuple.py Sun May 21 11:06:50 2006 @@ -66,6 +66,8 @@ def rtype_newtuple(hop): return TupleRepr._rtype_newtuple(hop) +newtuple = TupleRepr.newtuple + # # _________________________ Conversions _________________________ Modified: pypy/dist/pypy/rpython/ootypesystem/rtuple.py ============================================================================== --- pypy/dist/pypy/rpython/ootypesystem/rtuple.py (original) +++ pypy/dist/pypy/rpython/ootypesystem/rtuple.py Sun May 21 11:06:50 2006 @@ -58,6 +58,8 @@ def rtype_newtuple(hop): return TupleRepr._rtype_newtuple(hop) +newtuple = TupleRepr.newtuple + # ____________________________________________________________ # # Iteration. From fijal at codespeak.net Sun May 21 11:35:06 2006 From: fijal at codespeak.net (fijal at codespeak.net) Date: Sun, 21 May 2006 11:35:06 +0200 (CEST) Subject: [pypy-svn] r27527 - pypy/dist/pypy/translator/js2 Message-ID: <20060521093506.8639110061@code0.codespeak.net> Author: fijal Date: Sun May 21 11:34:56 2006 New Revision: 27527 Added: pypy/dist/pypy/translator/js2/js.py Log: Added missing file. Added: pypy/dist/pypy/translator/js2/js.py ============================================================================== --- (empty file) +++ pypy/dist/pypy/translator/js2/js.py Sun May 21 11:34:56 2006 @@ -0,0 +1,42 @@ +''' +reference material: + http://webreference.com/javascript/reference/core_ref/ + http://webreference.com/programming/javascript/ + http://mochikit.com/ + http://www.mozilla.org/js/spidermonkey/ + svn co http://codespeak.net/svn/kupu/trunk/ecmaunit +''' + +import py +import os + +from pypy.rpython.rmodel import inputconst +from pypy.rpython.typesystem import getfunctionptr +from pypy.rpython.lltypesystem import lltype +from pypy.rpython.ootypesystem import ootype +from pypy.tool.udir import udir +from pypy.translator.js2.log import log + +from pypy.translator.js2.asmgen import AsmGen +from pypy.translator.js2.jts import JTS +from pypy.translator.js2.opcodes import opcodes +from pypy.translator.js2.function import Function + +from pypy.translator.cli.gencli import GenCli + +def _path_join(root_path, *paths): + path = root_path + for p in paths: + path = os.path.join(path, p) + return path + +class JS(object): + def __init__ ( self , translator , functions=[] , stackless=False , compress=False , logging=False ): + self . cli = GenCli ( udir , translator , type_system_class = JTS , opcode_dict = opcodes ,\ + name_suffix = '.js' , function_class = Function ) + self . translator = translator + + def write_source ( self ): + self . cli . generate_source ( AsmGen ) + self . filename = self . cli . tmpfile + return self . cli . tmpfile From fijal at codespeak.net Sun May 21 11:48:17 2006 From: fijal at codespeak.net (fijal at codespeak.net) Date: Sun, 21 May 2006 11:48:17 +0200 (CEST) Subject: [pypy-svn] r27528 - pypy/dist/pypy/translator/cli Message-ID: <20060521094817.5000F10061@code0.codespeak.net> Author: fijal Date: Sun May 21 11:48:15 2006 New Revision: 27528 Modified: pypy/dist/pypy/translator/cli/gencli.py Log: Some compatibility issues on gencli/genjs line. Modified: pypy/dist/pypy/translator/cli/gencli.py ============================================================================== --- pypy/dist/pypy/translator/cli/gencli.py (original) +++ pypy/dist/pypy/translator/cli/gencli.py Sun May 21 11:48:15 2006 @@ -26,11 +26,12 @@ class GenCli(object): def __init__(self, tmpdir, translator, entrypoint = None, type_system_class = CTS, \ - opcode_dict = opcodes, name_suffix = '.il' ): + opcode_dict = opcodes, name_suffix = '.il', function_class = Function ): self.tmpdir = tmpdir self.translator = translator self.entrypoint = entrypoint - self.db = LowLevelDatabase( type_system_class = type_system_class , opcode_dict = opcode_dict ) + self.db = LowLevelDatabase( type_system_class = type_system_class , opcode_dict = opcode_dict, + function_class = function_class ) if entrypoint is None: self.assembly_name = self.translator.graphs[0].name From fijal at codespeak.net Sun May 21 12:12:00 2006 From: fijal at codespeak.net (fijal at codespeak.net) Date: Sun, 21 May 2006 12:12:00 +0200 (CEST) Subject: [pypy-svn] r27529 - in pypy/dist/pypy/translator/js2: . test Message-ID: <20060521101200.F29BF10061@code0.codespeak.net> Author: fijal Date: Sun May 21 12:11:58 2006 New Revision: 27529 Modified: pypy/dist/pypy/translator/js2/asmgen.py pypy/dist/pypy/translator/js2/function.py pypy/dist/pypy/translator/js2/js.py pypy/dist/pypy/translator/js2/jts.py pypy/dist/pypy/translator/js2/opcodes.py pypy/dist/pypy/translator/js2/test/test_runtest.py Log: PEP8 compatibility issues. Modified: pypy/dist/pypy/translator/js2/asmgen.py ============================================================================== --- pypy/dist/pypy/translator/js2/asmgen.py (original) +++ pypy/dist/pypy/translator/js2/asmgen.py Sun May 21 12:11:58 2006 @@ -4,7 +4,8 @@ from pypy.translator.js2.log import log -from pypy.translator.squeak.node import LoopFinder +from pypy.rpython.lltypesystem.lltype import Signed, Unsigned, Void, Bool, Float +from pypy.rpython.lltypesystem.lltype import SignedLongLong, UnsignedLongLong from StringIO import StringIO @@ -38,116 +39,123 @@ self._indent -= self._indentstep self.writeline(self._endblock) -class Queue ( object ): - def __init__ ( self , l , subst_table ): - self . l = l [:] - self . subst_table = subst_table - - def pop ( self ): - el = self . l . pop () - return self . subst_table . get ( el , el ) +class Queue(object): + def __init__(self, l, subst_table): + self.l = l[:] + self.subst_table = subst_table + + def pop(self): + el = self.l.pop() + return self.subst_table.get(el, el) - def __getattr__ ( self , attr ): - return getattr ( self . l , attr ) + def __getattr__(self,attr): + return getattr(self.l, attr) - def __len__ ( self ): + def __len__(self): return len(self.l) -class AsmGen ( object ): +class AsmGen(object): """ JS 'assembler' generator routines """ - def __init__ ( self , outfile , name ): - self . outfile = outfile - self . name = name - self . subst_table = {} - self . right_hand = Queue ( [] , self . subst_table ) - self . codegenerator = CodeGenerator ( outfile ) + def __init__(self, outfile, name): + self.outfile = outfile + self.name = name + self.subst_table = {} + self.right_hand = Queue([], self.subst_table) + self.codegenerator = CodeGenerator(outfile) - def show_const ( self ): + def show_const(self): return False - def begin_function ( self , name, arglist, returntype, is_entrypoint = False, *args ): - args = "," . join ( [ i [ 1 ] for i in arglist ] ) - self . codegenerator . write ( "function %s (%s) " % ( name , args ) ) - self . codegenerator . openblock () - - def end_function ( self ): - self . codegenerator . closeblock () - - def locals ( self , loc ): - self . codegenerator . writeline ( "var " + "," . join ( [ i [ 1 ] for i in loc ] ) + ";" ) - - def load_arg ( self , v ): - self . right_hand . append ( v.name ) - - def store_local ( self , v ): - name = self . subst_table . get ( v . name , v . name ) - element = self . right_hand . pop () + def begin_function(self, name, arglist, returntype, is_entrypoint = False, *args): + args = ",".join([i[1] for i in arglist]) + self.codegenerator.write("function %s (%s) "%(name, args)) + self.codegenerator.openblock() + + def end_function(self): + self.codegenerator.closeblock() + + def locals(self, loc): + self.codegenerator.writeline("var "+",".join([i[1] for i in loc])+";") + + def load_arg(self, v): + self.right_hand.append(v.name) + + def store_local(self, v): + name = self.subst_table.get(v.name, v.name) + element = self.right_hand.pop() if element != name: - self . codegenerator . writeline ( "%s = %s;" % ( name , element ) ) + self.codegenerator.writeline("%s = %s;"%(name, element)) - def load_local ( self , v ): - self . right_hand . append ( v . name ) + def load_local(self, v): + self.right_hand.append(v.name) - def load_const ( self , _type , v ): - self . right_hand . append ( str(v) ) + def load_const(self, _type, v): + if _type is Bool: + if v == False: + val = 'false' + else: + val = 'true' + else: + val = str(v) + self.right_hand.append(val) - def ret ( self ): - self . codegenerator . writeline ( "return ( %s );" % self . right_hand . pop () ) + def ret(self): + self.codegenerator.writeline("return ( %s );"%self.right_hand.pop()) - def begin_namespace ( self , namespace ): + def begin_namespace(self,namespace): pass - def end_namespace ( self ): + def end_namespace(self): pass - def begin_class ( self , cl ): - pass + def begin_class(self,cl): + raise NotImplementedError("Class support") - def end_class ( self ): - pass + def end_class(self): + raise NotImplementedError("Class support") - def emit ( self , opcode , *args ): - v1 = self . right_hand . pop () - v2 = self . right_hand . pop () - self . right_hand . append ( "(%s%s%s)" % ( v2 , opcode , v1 ) ) - - def call ( self , func ): - func_name,args = func - real_args = "," . join ( [ self . right_hand . pop () for i in xrange(len(args)) ] ) - self . right_hand . append ( "%s ( %s )" % ( func_name , real_args ) ) - - def branch_if ( self , arg , exitcase ): - arg_name = self . subst_table . get ( arg . name , arg . name ) - self . codegenerator . write ( "if ( %s == %s )" % ( arg_name , exitcase ) ) - self . codegenerator . openblock () - - def branch_while ( self , arg , exitcase ): - arg_name = self . subst_table . get ( arg . name , arg . name ) - self . codegenerator . write ( "while ( %s == %s )" % ( arg_name , exitcase ) ) - self . codegenerator . openblock () - - def branch_else ( self ): - self . codegenerator . closeblock () - self . codegenerator . write ( "else" ) - self . codegenerator . openblock () + def emit(self, opcode, *args): + v1 = self.right_hand.pop() + v2 = self.right_hand.pop() + self.right_hand.append("(%s%s%s)"%(v2, opcode, v1)) + + def call(self, func): + func_name, args = func + real_args = ",".join([self.right_hand.pop() for i in xrange(len(args))] ) + self.right_hand.append("%s ( %s )"%(func_name, real_args)) + + def branch_if(self, arg, exitcase): + arg_name = self.subst_table.get(arg.name, arg.name) + self.codegenerator.write("if ( %s == %s )"%(arg_name, str(exitcase).lower())) + self.codegenerator.openblock() + + def branch_while(self, arg, exitcase): + arg_name = self.subst_table.get(arg.name, arg.name) + self.codegenerator.write("while ( %s == %s )"%(arg_name, str(exitcase).lower())) + self.codegenerator.openblock() + + def branch_else(self): + self.codegenerator.closeblock() + self.codegenerator.write("else") + self.codegenerator.openblock() - def close_branch ( self ): - self . codegenerator . closeblock () + def close_branch(self): + self.codegenerator.closeblock() - def label ( self , *args ): - self . codegenerator . openblock () + def label(self, *args): + self.codegenerator.openblock() - def branch ( self , *args ): + def branch(self, *args): #self . codegenerator . closeblock () pass - def change_name ( self , from_name , to_name ): - self . subst_table [ from_name.name ] = to_name.name + def change_name(self, from_name, to_name): + self.subst_table[from_name.name] = to_name.name #pass - def cast_floor ( self ): - self . right_hand . append ( "Math.floor ( %s )" % self . right_hand . pop() ) + def cast_floor(self): + self.right_hand.append("Math.floor ( %s )"%self.right_hand.pop()) #def finish ( self ): # self . outfile . write ( "%r" % self . right_hand ) Modified: pypy/dist/pypy/translator/js2/function.py ============================================================================== --- pypy/dist/pypy/translator/js2/function.py (original) +++ pypy/dist/pypy/translator/js2/function.py Sun May 21 12:11:58 2006 @@ -82,62 +82,62 @@ for op in block.operations: self._render_op(op) - def render_block ( self , block , stop_block = None ): + def render_block(self, block, stop_block = None): if block is stop_block: return for op in block.operations: self._render_op(op) - if len ( block . exits ) == 0: + if len(block.exits) == 0: # return block return_var = block.inputargs[0] - self . load ( return_var ) - self . ilasm . ret () - elif block . exitswitch is None: + self.load(return_var) + self.ilasm.ret() + elif block.exitswitch is None: # single exit block - assert ( len(block.exits) == 1 ) - link = block . exits [ 0 ] - self . _setup_link ( link ) - self . render_block ( link . target , stop_block ) - elif block . exitswitch is flowmodel.c_last_exception: - raise NotImplementedError ( "Exception handling" ) + assert(len(block.exits) == 1) + link = block.exits[0] + self._setup_link(link) + self.render_block(link.target, stop_block) + elif block.exitswitch is flowmodel.c_last_exception: + raise NotImplementedError("Exception handling") else: - if self . loops . has_key ( block ): + if self.loops.has_key(block): # we've got loop - self . ilasm . branch_while ( block . exitswitch , self . loops [ block ] ) - exit_case = block . exits [ self . loops [ block ] ] - self . _setup_link ( exit_case ) - self . render_block ( exit_case . target , block ) - for op in block . operations: - self._render_op ( op ) - self . ilasm . close_branch () - exit_case = block . exits [ not self . loops [ block ] ] - self . _setup_link ( exit_case ) + self.ilasm.branch_while(block.exitswitch, self.loops[block]) + exit_case = block.exits[self.loops[block]] + self._setup_link(exit_case) + self.render_block(exit_case.target, block) + for op in block.operations: + self._render_op(op) + self.ilasm.close_branch() + exit_case = block.exits[not self.loops[block]] + self._setup_link(exit_case) #log ( ) - self . render_block ( exit_case . target , block ) + self.render_block(exit_case.target,block) #raise NotImplementedError ( "loop" ) else: # just a simple if - assert ( len ( block . exits ) == 2 ) - self . ilasm . branch_if ( block . exitswitch , True ) - self . _setup_link ( block . exits [ True ] ) - self . render_block ( block . exits [ True ] . target , stop_block ) - self . ilasm . branch_else () - self . _setup_link ( block . exits [ False ] ) - self . render_block ( block . exits [ False ] . target , stop_block ) - self . ilasm . close_branch () + assert(len(block.exits) == 2) + self.ilasm.branch_if(block.exitswitch, True) + self._setup_link(block.exits[True]) + self.render_block(block.exits[True].target, stop_block) + self.ilasm.branch_else() + self._setup_link(block.exits[False]) + self.render_block(block.exits[False].target, stop_block) + self.ilasm.close_branch() - def render ( self , ilasm ): - if self . db . graph_name ( self . graph ) is not None and not self . is_method: + def render(self,ilasm): + if self.db.graph_name(self.graph) is not None and not self.is_method: return # already rendered - self . ilasm = ilasm + self.ilasm = ilasm - self . loops = LoopFinder ( self . graph . startblock ) . loops - self . ilasm . begin_function ( self . name , self . args , None , None , None ) + self.loops = LoopFinder(self.graph.startblock).loops + self.ilasm.begin_function(self.name, self.args, None, None, None) - self . render_block ( self . graph . startblock ) + self.render_block(self.graph.startblock) ## if self._is_return_block(block): ## return_blocks.append(block) ## continue @@ -168,110 +168,6 @@ else: self.db.record_function(self.graph, self.name) - def oldrender(self, ilasm): - if self.db.graph_name(self.graph) is not None and not self.is_method: - return # already rendered - - loop_finder = LoopFinder ( self . graph . startblock ) - # Work out it here - - self.ilasm = ilasm - graph = self.graph - returntype, returnvar = self.cts.llvar_to_cts(graph.getreturnvar()) - - self.ilasm.begin_function(self.name, self.args, returntype, None , None ) - self.ilasm.locals(self.locals) - - return_blocks = [] - for block in graph.iterblocks(): - if self._is_return_block(block): - return_blocks.append(block) - continue - - - #self.ilasm.label(self._get_block_name(block)) - - handle_exc = (block.exitswitch == flowmodel.c_last_exception) - if handle_exc: - self.ilasm.begin_try() - - for op in block.operations: - #self._search_for_classes(op) - self._render_op(op) - - if self._is_raise_block(block): - exc = block.inputargs[1] - self.load(exc) - self.ilasm.throw() - - if handle_exc: - # search for the "default" block to be executed when no exception is raised - for link in block.exits: - if link.exitcase is None: - self._setup_link(link) - target_label = self._get_block_name(link.target) - self.ilasm.leave(target_label) - self.ilasm.end_try() - - # catch the exception and dispatch to the appropriate block - for link in block.exits: - if link.exitcase is None: - continue # see above - - assert issubclass(link.exitcase, Exception) - #cts_exc = self.cts.pyexception_to_cts(link.exitcase) - #cts_exc = str(link.exitcase) # TODO: is it a bit hackish? - ll_meta_exc = link.llexitcase - self.db.record_const(ll_meta_exc) - ll_exc = ll_meta_exc._inst.class_._INSTANCE - cts_exc = self.cts.lltype_to_cts(ll_exc, False) - self.ilasm.begin_catch(cts_exc) - - target = link.target - if self._is_raise_block(target): - # the exception value is on the stack, use it as the 2nd target arg - assert len(link.args) == 2 - assert len(target.inputargs) == 2 - self.store(link.target.inputargs[1]) - else: - # pop the unused exception value - self.ilasm.pop() - self._setup_link(link) - - target_label = self._get_block_name(target) - self.ilasm.leave(target_label) - self.ilasm.end_catch() - - else: - # no exception handling, follow block links - for link in block.exits: - target_label = self._get_block_name(link.target) - if link.exitcase is None: - pass - #self.ilasm.branch(target_label) - else: - assert type(link.exitcase is bool) - assert block.exitswitch is not None - self.ilasm.branch_if( block.exitswitch, link.exitcase, target_label) - self._setup_link(link) - self.ilasm.close_branch() - - # render return blocks at the end just to please the .NET - # runtime that seems to need a return statement at the end of - # the function - for block in return_blocks: - #self.ilasm.label(self._get_block_name(block)) - return_var = block.inputargs[0] - if return_var.concretetype is not Void: - self.load(return_var) - self.ilasm.ret() - - self.ilasm.end_function() - if self.is_method: - pass # TODO - else: - self.db.record_function(self.graph, self.name) - def _setup_link(self, link): target = link.target for to_load, to_store in zip(link.args, target.inputargs): Modified: pypy/dist/pypy/translator/js2/js.py ============================================================================== --- pypy/dist/pypy/translator/js2/js.py (original) +++ pypy/dist/pypy/translator/js2/js.py Sun May 21 12:11:58 2006 @@ -31,12 +31,12 @@ return path class JS(object): - def __init__ ( self , translator , functions=[] , stackless=False , compress=False , logging=False ): - self . cli = GenCli ( udir , translator , type_system_class = JTS , opcode_dict = opcodes ,\ - name_suffix = '.js' , function_class = Function ) - self . translator = translator + def __init__(self, translator, functions=[], stackless=False, compress=False, logging=False): + self.cli = GenCli(udir, translator, type_system_class = JTS, opcode_dict = opcodes,\ + name_suffix = '.js', function_class = Function) + self.translator = translator - def write_source ( self ): - self . cli . generate_source ( AsmGen ) - self . filename = self . cli . tmpfile - return self . cli . tmpfile + def write_source(self): + self.cli.generate_source(AsmGen) + self.filename = self.cli.tmpfile + return self.cli.tmpfile Modified: pypy/dist/pypy/translator/js2/jts.py ============================================================================== --- pypy/dist/pypy/translator/js2/jts.py (original) +++ pypy/dist/pypy/translator/js2/jts.py Sun May 21 12:11:58 2006 @@ -4,15 +4,15 @@ from pypy.rpython.ootypesystem import ootype -class JTS ( object ): +class JTS(object): """ Class implementing JavaScript type system calls with mapping similiar to cts """ - def __init__ ( self , db ): - self . db = db + def __init__(self, db): + self.db = db - def llvar_to_cts ( self , var ): - return 'var ',var.name + def llvar_to_cts(self, var): + return 'var ', var.name def graph_to_signature(self, graph, is_method = False, func_name = None): ret_type, ret_var = self.llvar_to_cts(graph.getreturnvar()) Modified: pypy/dist/pypy/translator/js2/opcodes.py ============================================================================== --- pypy/dist/pypy/translator/js2/opcodes.py (original) +++ pypy/dist/pypy/translator/js2/opcodes.py Sun May 21 12:11:58 2006 @@ -7,16 +7,16 @@ DoNothing = [PushAllArgs] -class _SameAs ( MicroInstruction ): - def render ( self , generator , op ): - generator.change_name(op.result,op.args[0]) +class _SameAs(MicroInstruction): + def render(self, generator, op): + generator.change_name(op.result, op.args[0]) -class _CastFloor ( MicroInstruction ): - def render ( self , generator , op ): +class _CastFloor(MicroInstruction): + def render(self, generator, op): generator.cast_floor() -CastFloor = [ PushAllArgs , _CastFloor() ] -CopyName = [ PushAllArgs , _SameAs () ] +CastFloor = [PushAllArgs, _CastFloor()] +CopyName = [PushAllArgs, _SameAs ()] SameAs = CopyName opcodes = {'int_mul': '*', @@ -59,6 +59,13 @@ 'unichar_ne': '!=', 'unichar_ge': '>=', 'unichar_gt': '>', + + 'char_lt': '<', + 'char_le': '<=', + 'char_eq': '==', + 'char_ne': '!=', + 'char_ge': '>=', + 'char_gt': '>', 'float_mul': '*', 'float_add': '+', @@ -92,6 +99,7 @@ 'cast_int_to_float': CopyName, 'cast_int_to_longlong': CopyName, 'cast_uint_to_int': CopyName, + 'cast_uint_to_float': CopyName, 'cast_float_to_int': CastFloor, 'cast_float_to_uint': CastFloor, 'truncate_longlong_to_int': CopyName, Modified: pypy/dist/pypy/translator/js2/test/test_runtest.py ============================================================================== --- pypy/dist/pypy/translator/js2/test/test_runtest.py (original) +++ pypy/dist/pypy/translator/js2/test/test_runtest.py Sun May 21 12:11:58 2006 @@ -2,17 +2,16 @@ from pypy.translator.js2.test.runtest import compile_function #test returntypes -##def test_bool_return(): -## def bool_return_False(): -## return False -## def bool_return_True(): -## return True -## f_false = compile_function(bool_return_False, []) -## assert f_false() == bool_return_False() -## f_true = compile_function(bool_return_True , []) -## assert f_true() == bool_return_True() -## -## +def test_bool_return(): + def bool_return_False(): + return False + def bool_return_True(): + return True + f_false = compile_function(bool_return_False, []) + assert f_false() == bool_return_False() + f_true = compile_function(bool_return_True , []) + assert f_true() == bool_return_True() + def test_int_return(): def int_return(): return 42 From fijal at codespeak.net Sun May 21 12:23:11 2006 From: fijal at codespeak.net (fijal at codespeak.net) Date: Sun, 21 May 2006 12:23:11 +0200 (CEST) Subject: [pypy-svn] r27530 - pypy/dist/pypy/translator/js2/test Message-ID: <20060521102311.1E22010061@code0.codespeak.net> Author: fijal Date: Sun May 21 12:23:09 2006 New Revision: 27530 Added: pypy/dist/pypy/translator/js2/test/test_merge_if_blocks.py Log: Added another passing test Added: pypy/dist/pypy/translator/js2/test/test_merge_if_blocks.py ============================================================================== --- (empty file) +++ pypy/dist/pypy/translator/js2/test/test_merge_if_blocks.py Sun May 21 12:23:09 2006 @@ -0,0 +1,81 @@ +import py + +from pypy.translator.js2.test.runtest import compile_function + +import sys + +def test_merge_if_blocks_simple(): + def merge_if_blocks_simple(i): + if i == 5: + return 1005 + else: + return 2222 + simple = compile_function(merge_if_blocks_simple, [int]) + for i in range(-20,20): + assert simple(i) == merge_if_blocks_simple(i) + +def test_merge_if_blocks_basic(): + def merge_if_blocks_basic(i): + if i == 5: + return 1005 + elif i == 8: + return 1008 + return 2222 + basic = compile_function(merge_if_blocks_basic , [int]) + for i in range(-20,20): + assert basic(i) == merge_if_blocks_basic(i) + +def test_merge_if_blocks_chr(): + py.test.skip("String support in ootypesystem") + def merge_if_blocks_chr(i): + c = chr(i) + if c == '\x05': + return 1005 + elif c == '!': + return 1008 + return 2222 + basic = compile_function(merge_if_blocks_chr , [int]) + for i in range(0, 50): + assert basic(i) == merge_if_blocks_chr(i) + +def test_merge_if_blocks_uni(): + py.test.skip("String support in ootypesystem") + def merge_if_blocks_uni(i): + c = unichr(i) + if c == u'\x05': + return 1005 + elif c == u'!': + return 1008 + return 2222 + basic = compile_function(merge_if_blocks_uni , [int]) + for i in range(0, 50): + assert basic(i) == merge_if_blocks_uni(i) + + +def test_merge_if_blocks_many(): + def merge_if_blocks_many(i): + if i == 0: + return 1000 + elif i == 1: + return 1001 + elif i == 2: + return 1002 + elif i == 3: + return 1003 + elif i == 4: + return 1004 + elif i == 5: + return 1005 + elif i == 6: + return 1006 + elif i == 7: + return 1007 + elif i == 8: + return 1008 + elif i == 9: + return 1009 + else: + return 2222 + many = compile_function(merge_if_blocks_many , [int]) + for i in range(-20,20): + assert many(i) == merge_if_blocks_many(i) From antocuni at codespeak.net Sun May 21 15:32:13 2006 From: antocuni at codespeak.net (antocuni at codespeak.net) Date: Sun, 21 May 2006 15:32:13 +0200 (CEST) Subject: [pypy-svn] r27536 - pypy/dist/pypy/translator/cli/test Message-ID: <20060521133213.95F1E10075@code0.codespeak.net> Author: antocuni Date: Sun May 21 15:32:02 2006 New Revision: 27536 Modified: pypy/dist/pypy/translator/cli/test/compile.py pypy/dist/pypy/translator/cli/test/runtest.py Log: Fixed a bug that prevented some tests to pass on system with non-english locales. Modified: pypy/dist/pypy/translator/cli/test/compile.py ============================================================================== --- pypy/dist/pypy/translator/cli/test/compile.py (original) +++ pypy/dist/pypy/translator/cli/test/compile.py Sun May 21 15:32:02 2006 @@ -31,14 +31,12 @@ def foo(a, b): pass -from pypy.rpython.rarithmetic import ovfcheck - def bar(x, y): - try: - l = [x, y] - return l[0] - except IndexError: - return 0 + if x: + return 1 + else: + return None + f = compile_function(bar, [int, int]) Modified: pypy/dist/pypy/translator/cli/test/runtest.py ============================================================================== --- pypy/dist/pypy/translator/cli/test/runtest.py (original) +++ pypy/dist/pypy/translator/cli/test/runtest.py Sun May 21 15:32:02 2006 @@ -98,6 +98,7 @@ t.graphs.insert(0, graph) else: t.buildannotator().build_types(func, annotation) + t.buildrtyper(type_system="ootype").specialize() self.graph = t.graphs[0] @@ -131,7 +132,10 @@ py.test.skip("Compilation disabled") arglist = SDK.runtime() + [self._exe] + map(str, args) - mono = subprocess.Popen(arglist, stdout=subprocess.PIPE, stderr=subprocess.PIPE) + env = os.environ.copy() + env['LANG'] = 'C' + mono = subprocess.Popen(arglist, stdout=subprocess.PIPE, + stderr=subprocess.PIPE, env=env) stdout, stderr = mono.communicate() retval = mono.wait() assert retval == 0, stderr From arigo at codespeak.net Sun May 21 18:40:08 2006 From: arigo at codespeak.net (arigo at codespeak.net) Date: Sun, 21 May 2006 18:40:08 +0200 (CEST) Subject: [pypy-svn] r27541 - in pypy/dist/pypy: annotation rpython rpython/lltypesystem rpython/lltypesystem/test rpython/memory/test rpython/rctypes Message-ID: <20060521164008.F282510076@code0.codespeak.net> Author: arigo Date: Sun May 21 18:40:05 2006 New Revision: 27541 Added: pypy/dist/pypy/rpython/rgc.py (contents, props changed) Modified: pypy/dist/pypy/annotation/model.py pypy/dist/pypy/rpython/lltypesystem/lltype.py pypy/dist/pypy/rpython/lltypesystem/test/test_lltype.py pypy/dist/pypy/rpython/memory/test/test_gctransform.py pypy/dist/pypy/rpython/memory/test/test_transformed_gc.py pypy/dist/pypy/rpython/rctypes/implementation.py pypy/dist/pypy/rpython/rexternalobj.py pypy/dist/pypy/rpython/rmodel.py pypy/dist/pypy/rpython/rtyper.py Log: (some pedronis, arigo) * added pypy.rpython.rgc with an RPython interface to the gc_x_swap_pool and gc_x_clone operations. * made SomeExternalObject use the extregistry too. * bug fixes; extended cast_opaque_ptr to also do a cast_pointer for you. Modified: pypy/dist/pypy/annotation/model.py ============================================================================== --- pypy/dist/pypy/annotation/model.py (original) +++ pypy/dist/pypy/annotation/model.py Sun May 21 18:40:05 2006 @@ -405,9 +405,10 @@ class SomeExternalObject(SomeObject): - """Stands for an object of 'external' type. External types are defined - in pypy.rpython.extfunctable.declaretype(), and represent simple types - with some methods that need direct back-end support.""" + """Stands for an object of 'external' type. External types have a Repr + controlled by pypy.rpython.extregistry; or they come from the (obsolete) + table created by pypy.rpython.extfunctable.declaretype() and represent + simple types with some methods that need direct back-end support.""" def __init__(self, knowntype): self.knowntype = knowntype @@ -415,7 +416,7 @@ def can_be_none(self): return True -class SomeCTypesObject(SomeObject): +class SomeCTypesObject(SomeExternalObject): """Stands for an object of the ctypes module.""" NOMEMORY = "NOMEMORY" Modified: pypy/dist/pypy/rpython/lltypesystem/lltype.py ============================================================================== --- pypy/dist/pypy/rpython/lltypesystem/lltype.py (original) +++ pypy/dist/pypy/rpython/lltypesystem/lltype.py Sun May 21 18:40:05 2006 @@ -679,13 +679,10 @@ try: container = ptr._obj.container except AttributeError: - raise RuntimeError("%r does not come from a container" % (ptr,)) - if typeOf(container) != PTRTYPE.TO: - raise RuntimeError("%r contains a container of the wrong type:\n" - "%r instead of %r" % (ptr, typeOf(container), - PTRTYPE.TO)) + raise InvalidCast("%r does not come from a container" % (ptr,)) solid = getattr(ptr._obj, 'solid', False) - return _ptr(PTRTYPE, container, solid) + p = _ptr(Ptr(typeOf(container)), container, solid) + return cast_pointer(PTRTYPE, p) elif (not isinstance(CURTYPE.TO, OpaqueType) and isinstance(PTRTYPE.TO, OpaqueType)): if not ptr: @@ -699,7 +696,7 @@ try: container = ptr._obj.container except AttributeError: - raise RuntimeError("%r does not come from a container" % (ptr,)) + raise InvalidCast("%r does not come from a container" % (ptr,)) return opaqueptr(PTRTYPE.TO, 'hidden', container = container, solid = ptr._obj.solid) Modified: pypy/dist/pypy/rpython/lltypesystem/test/test_lltype.py ============================================================================== --- pypy/dist/pypy/rpython/lltypesystem/test/test_lltype.py (original) +++ pypy/dist/pypy/rpython/lltypesystem/test/test_lltype.py Sun May 21 18:40:05 2006 @@ -470,7 +470,7 @@ py.test.raises(TypeError, "cast_opaque_ptr(Ptr(S), o1)") py.test.raises(TypeError, "cast_opaque_ptr(Ptr(O1), s)") S2 = Struct('S2', ('z', Signed)) - py.test.raises(RuntimeError, "cast_opaque_ptr(Ptr(S2), o1)") + py.test.raises(InvalidCast, "cast_opaque_ptr(Ptr(S2), o1)") def test_is_atomic(): U = Struct('inlined', ('z', Signed)) Modified: pypy/dist/pypy/rpython/memory/test/test_gctransform.py ============================================================================== --- pypy/dist/pypy/rpython/memory/test/test_gctransform.py (original) +++ pypy/dist/pypy/rpython/memory/test/test_gctransform.py Sun May 21 18:40:05 2006 @@ -64,7 +64,7 @@ t = TranslationContext() t.buildannotator().build_types(func, inputtypes) if specialize: - t.buildrtyper().specialize(t) + t.buildrtyper().specialize() return t def rtype_and_transform(func, inputtypes, transformcls, specialize=True, check=True): @@ -442,7 +442,7 @@ pass t = TranslationContext() t.buildannotator().build_types(f, []) - t.buildrtyper().specialize(t) + t.buildrtyper().specialize() transformer = cls(t) fptr = getattr(transformer, attr)(TYPE) transformer.finish() @@ -554,7 +554,7 @@ pass t = TranslationContext() t.buildannotator().build_types(f, []) - t.buildrtyper().specialize(t) + t.buildrtyper().specialize() transformer = gctransform.RefcountingGCTransformer(t) p_S = transformer.dynamic_deallocation_funcptr_for_type(S) p_S1 = transformer.dynamic_deallocation_funcptr_for_type(S1) Modified: pypy/dist/pypy/rpython/memory/test/test_transformed_gc.py ============================================================================== --- pypy/dist/pypy/rpython/memory/test/test_transformed_gc.py (original) +++ pypy/dist/pypy/rpython/memory/test/test_transformed_gc.py Sun May 21 18:40:05 2006 @@ -170,7 +170,7 @@ t = TranslationContext() t.buildannotator().build_types(func, inputtypes) if specialize: - t.buildrtyper().specialize(t) + t.buildrtyper().specialize() if conftest.option.view: t.view() return t @@ -382,6 +382,40 @@ res = run([]) assert res == 111222333 + def test_cloning_highlevel(self): + from pypy.rpython import rgc + class A: + pass + class B(A): + pass + def func(n, dummy): + if n > 5: + x = A() + else: + x = B() + x.bvalue = 123 + x.next = A() + x.next.next = x + y, newpool = rgc.gc_clone(x, None) + assert y is not x + assert y.next is not x + assert y is not x.next + assert y.next is not x.next + assert y is not y.next + assert y is y.next.next + if isinstance(y, B): + assert n <= 5 + assert y.bvalue == 123 + else: + assert n > 5 + return 1 + + run = self.runner(func, nbargs=2) + res = run([3, 0]) + assert res == 1 + res = run([7, 0]) + assert res == 1 + def test_tree_cloning(self): import os # this makes a tree of calls. Each leaf stores its path (a linked Modified: pypy/dist/pypy/rpython/rctypes/implementation.py ============================================================================== --- pypy/dist/pypy/rpython/rctypes/implementation.py (original) +++ pypy/dist/pypy/rpython/rctypes/implementation.py Sun May 21 18:40:05 2006 @@ -118,15 +118,3 @@ import pypy.rpython.rctypes.avoid_p import pypy.rpython.rctypes.astringbuf import pypy.rpython.rctypes.apyobject - - -# Register the correspondance between SomeCTypesObject and the get_repr() -# functions attached to the extregistry to create CTypesReprs - -class __extend__( SomeCTypesObject ): - def rtyper_makerepr( self, rtyper ): - entry = extregistry.lookup_type(self.knowntype) - return entry.get_repr(rtyper, self) - - def rtyper_makekey( self ): - return self.__class__, self.knowntype, self.memorystate Modified: pypy/dist/pypy/rpython/rexternalobj.py ============================================================================== --- pypy/dist/pypy/rpython/rexternalobj.py (original) +++ pypy/dist/pypy/rpython/rexternalobj.py Sun May 21 18:40:05 2006 @@ -5,16 +5,33 @@ from pypy.rpython import rbuiltin from pypy.rpython.module.support import init_opaque_object from pypy.objspace.flow.model import Constant +from pypy.rpython import extregistry class __extend__(annmodel.SomeExternalObject): + def rtyper_makerepr(self, rtyper): - return ExternalObjRepr(self.knowntype) + if self.knowntype in typetable: + return ExternalObjRepr(self.knowntype) + else: + # delegate to the get_repr() of the extregistrered Entry class + entry = extregistry.lookup_type(self.knowntype) + return entry.get_repr(rtyper, self) + def rtyper_makekey(self): - return self.__class__, self.knowntype + # grab all attributes of the SomeExternalObject for the key + attrs = lltype.frozendict(self.__dict__) + if 'const' in attrs: + del attrs['const'] + if 'const_box' in attrs: + del attrs['const_box'] + return self.__class__, attrs class ExternalObjRepr(Repr): + """Repr for the (obsolecent) extfunctable.declaretype() case. + If you use the extregistry instead you get to pick your own Repr. + """ def __init__(self, knowntype): self.exttypeinfo = typetable[knowntype] Added: pypy/dist/pypy/rpython/rgc.py ============================================================================== --- (empty file) +++ pypy/dist/pypy/rpython/rgc.py Sun May 21 18:40:05 2006 @@ -0,0 +1,94 @@ +from pypy.rpython.extregistry import ExtRegistryEntry + +# ____________________________________________________________ +# Framework GC features + +class GcPool(object): + pass + +def gc_swap_pool(newpool): + """Set newpool as the current pool (create one if newpool is None). + All malloc'ed objects are put into the current pool;this is a + way to separate objects depending on when they were allocated. + """ + raise NotImplementedError("only works in stacklessgc translated versions") + +def gc_clone(gcobject, pool): + """Recursively clone the gcobject and everything it points to, + directly or indirectly -- but stops at objects that are not + in the specified pool. Pool can be None to mean the current one. + A new pool is built to contain the copies. Return (newobject, newpool). + """ + raise NotImplementedError("only works in stacklessgc translated versions") + +# ____________________________________________________________ +# Annotation and specialization + +class GcPoolEntry(ExtRegistryEntry): + "Link GcPool to its Repr." + _type_ = GcPool + + def get_repr(self, rtyper, s_pool): + from pypy.rpython.rmodel import SimplePointerRepr + from pypy.rpython.memory.gc import X_POOL_PTR + return SimplePointerRepr(X_POOL_PTR) + + +class SwapPoolFnEntry(ExtRegistryEntry): + "Annotation and specialization of gc_swap_pool()." + _about_ = gc_swap_pool + + def compute_result_annotation(self, s_newpool): + from pypy.annotation import model as annmodel + return annmodel.SomeExternalObject(GcPool) + + def specialize_call(self, hop): + from pypy.annotation import model as annmodel + s_pool_ptr = annmodel.SomeExternalObject(GcPool) + r_pool_ptr = hop.rtyper.getrepr(s_pool_ptr) + vlist = hop.inputargs(r_pool_ptr) + return hop.genop('gc_x_swap_pool', vlist, resulttype = r_pool_ptr) + + +class CloneFnEntry(ExtRegistryEntry): + "Annotation and specialization of gc_clone()." + _about_ = gc_clone + + def compute_result_annotation(self, s_gcobject, s_pool): + from pypy.annotation import model as annmodel + return annmodel.SomeTuple([s_gcobject, + annmodel.SomeExternalObject(GcPool)]) + + def specialize_call(self, hop): + from pypy.rpython.error import TyperError + from pypy.rpython.lltypesystem import lltype, llmemory, rtuple + r_gcobject = hop.args_r[0] + if (not isinstance(r_gcobject.lowleveltype, lltype.Ptr) or + not isinstance(r_gcobject.lowleveltype.TO, lltype.GC_CONTAINER)): + raise TyperError("gc_clone() can only clone a dynamically " + "allocated object;\ngot %r" % (r_gcobject,)) + from pypy.annotation import model as annmodel + from pypy.rpython.memory.gc import X_CLONE, X_CLONE_PTR + s_pool_ptr = annmodel.SomeExternalObject(GcPool) + r_pool_ptr = hop.rtyper.getrepr(s_pool_ptr) + r_tuple = hop.r_result + + c_CLONE = hop.inputconst(lltype.Void, X_CLONE) + c_gcobjectptr = hop.inputconst(lltype.Void, "gcobjectptr") + c_pool = hop.inputconst(lltype.Void, "pool") + + v_gcobject, v_pool = hop.inputargs(hop.args_r[0], r_pool_ptr) + v_gcobjectptr = hop.genop('cast_opaque_ptr', [v_gcobject], + resulttype = llmemory.GCREF) + v_clonedata = hop.genop('malloc', [c_CLONE], + resulttype = X_CLONE_PTR) + hop.genop('setfield', [v_clonedata, c_gcobjectptr, v_gcobjectptr]) + hop.genop('setfield', [v_clonedata, c_pool, v_pool]) + hop.genop('gc_x_clone', [v_clonedata]) + v_gcobjectptr = hop.genop('getfield', [v_clonedata, c_gcobjectptr], + resulttype = llmemory.GCREF) + v_pool = hop.genop('getfield', [v_clonedata, c_pool], + resulttype = r_pool_ptr) + v_gcobject = hop.genop('cast_opaque_ptr', [v_gcobjectptr], + resulttype = r_tuple.items_r[0]) + return rtuple.newtuple(hop.llops, r_tuple, [v_gcobject, v_pool]) Modified: pypy/dist/pypy/rpython/rmodel.py ============================================================================== --- pypy/dist/pypy/rpython/rmodel.py (original) +++ pypy/dist/pypy/rpython/rmodel.py Sun May 21 18:40:05 2006 @@ -344,6 +344,18 @@ get_ll_fasthash_function = get_ll_hash_function impossible_repr = VoidRepr() +class SimplePointerRepr(Repr): + "Convenience Repr for simple ll pointer types with no operation on them." + + def __init__(self, lowleveltype): + self.lowleveltype = lowleveltype + + def convert_const(self, value): + if value is not None: + raise TyperError("%r only supports None as prebuilt constant, " + "got %r" % (self, value)) + return lltype.nullptr(self.lowleveltype.TO) + # ____________________________________________________________ def inputdesc(reqtype, desc): Modified: pypy/dist/pypy/rpython/rtyper.py ============================================================================== --- pypy/dist/pypy/rpython/rtyper.py (original) +++ pypy/dist/pypy/rpython/rtyper.py Sun May 21 18:40:05 2006 @@ -158,6 +158,7 @@ """Main entry point: specialize all annotated blocks of the program.""" self.crash_on_first_typeerror = crash_on_first_typeerror # specialize depends on annotator simplifications + assert dont_simplify_again in (False, True) # safety check if not dont_simplify_again: self.annotator.simplify() From arigo at codespeak.net Sun May 21 21:01:26 2006 From: arigo at codespeak.net (arigo at codespeak.net) Date: Sun, 21 May 2006 21:01:26 +0200 (CEST) Subject: [pypy-svn] r27547 - in pypy/dist/pypy/translator/c: . test Message-ID: <20060521190126.0A4C810076@code0.codespeak.net> Author: arigo Date: Sun May 21 21:01:25 2006 New Revision: 27547 Modified: pypy/dist/pypy/translator/c/gc.py pypy/dist/pypy/translator/c/test/test_newgc.py Log: Fix and test for when __del__ bodies are put in the database by the framework gc policy. Modified: pypy/dist/pypy/translator/c/gc.py ============================================================================== --- pypy/dist/pypy/translator/c/gc.py (original) +++ pypy/dist/pypy/translator/c/gc.py Sun May 21 21:01:25 2006 @@ -352,7 +352,11 @@ transformerclass = gctransform.FrameworkGCTransformer def struct_setup(self, structdefnode, rtti): - pass + if rtti is not None and hasattr(rtti._obj, 'destructor_funcptr'): + destrptr = rtti._obj.destructor_funcptr + # make sure this is seen by the database early, i.e. before + # finish() on the gctransformer + self.db.get(destrptr) def array_setup(self, arraydefnode): pass Modified: pypy/dist/pypy/translator/c/test/test_newgc.py ============================================================================== --- pypy/dist/pypy/translator/c/test/test_newgc.py (original) +++ pypy/dist/pypy/translator/c/test/test_newgc.py Sun May 21 21:01:25 2006 @@ -625,6 +625,19 @@ res = fn() assert res == 123 + def test_framework_del_seeing_new_types(self): + class B(object): + pass + class A(object): + def __del__(self): + B() + def f(): + A() + return 42 + fn = self.getcompiled(f) + res = fn() + assert res == 42 + class TestUsingStacklessFramework(TestUsingFramework): from pypy.translator.c.gc import StacklessFrameworkGcPolicy as gcpolicy From cfbolz at codespeak.net Sun May 21 21:05:51 2006 From: cfbolz at codespeak.net (cfbolz at codespeak.net) Date: Sun, 21 May 2006 21:05:51 +0200 (CEST) Subject: [pypy-svn] r27548 - in pypy/dist/pypy: rpython/memory/test translator/c/test Message-ID: <20060521190551.64AAC10074@code0.codespeak.net> Author: cfbolz Date: Sun May 21 21:05:49 2006 New Revision: 27548 Modified: pypy/dist/pypy/rpython/memory/test/test_transformed_gc.py pypy/dist/pypy/translator/c/test/test_newgc.py Log: add weakref tests for framework. seems to work fine :-) Modified: pypy/dist/pypy/rpython/memory/test/test_transformed_gc.py ============================================================================== --- pypy/dist/pypy/rpython/memory/test/test_transformed_gc.py (original) +++ pypy/dist/pypy/rpython/memory/test/test_transformed_gc.py Sun May 21 21:05:49 2006 @@ -336,7 +336,6 @@ b.num_deleted += 1 def f(x, y): a = A() - c = C() i = 0 while i < x: i += 1 @@ -346,7 +345,7 @@ return b.num_deleted run = self.runner(f, nbargs=2) res = run([5, 42]) #XXX pure lazyness here too - assert res == 13 + assert res == 12 def test_cloning(self): B = lltype.GcStruct('B', ('x', lltype.Signed)) Modified: pypy/dist/pypy/translator/c/test/test_newgc.py ============================================================================== --- pypy/dist/pypy/translator/c/test/test_newgc.py (original) +++ pypy/dist/pypy/translator/c/test/test_newgc.py Sun May 21 21:05:49 2006 @@ -598,6 +598,100 @@ res = fn() assert res == -70 + def test_framework_finalizer(self): + class B(object): + pass + b = B() + b.nextid = 0 + b.num_deleted = 0 + class A(object): + def __init__(self): + self.id = b.nextid + b.nextid += 1 + def __del__(self): + b.num_deleted += 1 + def f(): + a = A() + i = 0 + while i < 5: + i += 1 + a = A() + llop.gc__collect(lltype.Void) + llop.gc__collect(lltype.Void) + return b.num_deleted + run = self.getcompiled(f) + res = run() + assert res == 6 + + def test_framework_weakref_alive(self): + def func(): + f = Weakrefable() + f.x = 32 + ref1 = get_weakref(f) + ref2 = get_weakref(f) + return f.x + ref2.ref().x + assert func() == 64 + f = self.getcompiled(func) + assert f() == 64 + + def test_framework_weakref_dying(self): + def g(): + f = Weakrefable() + f.x = 32 + return get_weakref(f) + def func(): + ref = g() + llop.gc__collect(lltype.Void) + llop.gc__collect(lltype.Void) + return ref.ref() is None + f = self.getcompiled(func) + assert f() + + def test_framework_weakref_callback(self): + global_w = Weakrefable() + global_w.x = 31 + def g(ref): + global_w.x = 32 + def h(): + f = Weakrefable() + f.x = 32 + ref = get_weakref(f, g) + return ref + def func(): + ref = h() + llop.gc__collect(lltype.Void) + llop.gc__collect(lltype.Void) + return (ref.ref() is None and ref.callback is not None and + global_w.x == 32) + f = self.getcompiled(func) + assert f() + + def test_framework_weakref_dont_always_callback(self): + global_w1 = Weakrefable() + global_w1.x = 30 + global_w2 = Weakrefable() + global_w2.x = 30 + def g1(ref): + global_w1.x = 32 + def g2(ref): + global_w2.x = 32 + def h(): + f = Weakrefable() + f.x = 32 + ref1 = get_weakref(f, g1) + ref2 = get_weakref(f, g2) + if f.x % 2 == 0: # start a new block to make sure ref2 dies before f + ref2 = None + f.x = 12 + llop.gc__collect(lltype.Void) + llop.gc__collect(lltype.Void) + return ref1 + def func(): + ref = h() + return global_w1.x == 32 and global_w2.x == 30 + f = compile_func(func, []) + assert f() + def test_framework_malloc_raw(self): A = lltype.Struct('A', ('value', lltype.Signed)) From mwh at codespeak.net Mon May 22 01:07:16 2006 From: mwh at codespeak.net (mwh at codespeak.net) Date: Mon, 22 May 2006 01:07:16 +0200 (CEST) Subject: [pypy-svn] r27564 - pypy/dist/pypy/rpython/memory Message-ID: <20060521230716.F114010076@code0.codespeak.net> Author: mwh Date: Mon May 22 01:07:15 2006 New Revision: 27564 Modified: pypy/dist/pypy/rpython/memory/gc.py Log: another version of x_become(), copying what collect() looks like now :) still doesn't work. Modified: pypy/dist/pypy/rpython/memory/gc.py ============================================================================== --- pypy/dist/pypy/rpython/memory/gc.py (original) +++ pypy/dist/pypy/rpython/memory/gc.py Mon May 22 01:07:15 2006 @@ -531,18 +531,73 @@ # reinstall the pool that was current at the beginning of x_clone() clonedata.pool = self.x_swap_pool(curpool) + def add_reachable_to_stack2(self, obj, objects, target_addr, source_addr): + size_gc_header = self.gcheaderbuilder.size_gc_header + gc_info = obj - size_gc_header + hdr = llmemory.cast_adr_to_ptr(gc_info, self.HDRPTR) + if hdr.typeid & 1: + return + typeid = hdr.typeid >> 1 + offsets = self.offsets_to_gc_pointers(typeid) + i = 0 + while i < len(offsets): + pointer = obj + offsets[i] + objects.append(pointer.address[0]) + # ------------------------------------------------- + # begin difference from collect + llop.debug_debug(lltype.Void, + pointer.address[0], target_addr, + pointer.address[0] == target_addr, + ) + if pointer.address[0] == target_addr: + pointer.address[0] = source_addr + # end difference from collect + # ------------------------------------------------- + i += 1 + if self.is_varsize(typeid): + offset = self.varsize_offset_to_variable_part( + typeid) + length = (obj + self.varsize_offset_to_length(typeid)).signed[0] + obj += offset + offsets = self.varsize_offsets_to_gcpointers_in_var_part(typeid) + itemlength = self.varsize_item_sizes(typeid) + i = 0 + while i < length: + item = obj + itemlength * i + j = 0 + while j < len(offsets): + objects.append((item + offsets[j]).address[0]) + # ------------------------------------------------- + # begin difference from collect + pointer = item + offsets[j] + if pointer.address[0] == target_addr: + pointer.address[0] = source_addr + ## end difference from collect + # ------------------------------------------------- + j += 1 + i += 1 + + def x_become(self, target_addr, source_addr): - # become is implemented very very much like collect currently... - import os, time + # 1. mark from the roots, and also the objects that objects-with-del + # point to (using the list of malloced_objects_with_finalizer) + # 2. walk the list of objects-without-del and free the ones not marked + # 3. walk the list of objects-with-del and for the ones not marked: + # call __del__, move the object to the list of object-without-del + import time + from pypy.rpython.lltypesystem.lloperation import llop if DEBUG_PRINT: - os.write(2, 'becoming...\n') + llop.debug_print(lltype.Void, 'collecting...') start_time = time.time() roots = self.get_roots() size_gc_header = self.gcheaderbuilder.size_gc_header - objects = self.AddressLinkedList() +## llop.debug_view(lltype.Void, self.malloced_objects, self.poolnodes, +## size_gc_header) + + # push the roots on the mark stack + objects = self.AddressLinkedList() # mark stack while 1: curr = roots.pop() -## print "root: ", curr if curr == NULL: break # roots is a list of addresses to addresses: @@ -562,48 +617,37 @@ # from this point onwards, no more mallocs should be possible old_malloced = self.bytes_malloced self.bytes_malloced = 0 + curr_heap_size = 0 + freed_size = 0 + + # mark objects reachable by objects with a finalizer, but not those + # themselves. add their size to curr_heap_size, since they always + # survive the collection + hdr = self.malloced_objects_with_finalizer + while hdr: + next = hdr.next + typeid = hdr.typeid >> 1 + gc_info = llmemory.cast_ptr_to_adr(hdr) + obj = gc_info + size_gc_header + self.add_reachable_to_stack2(obj, objects, target_addr, source_addr) + addr = llmemory.cast_ptr_to_adr(hdr) + size = self.fixed_size(typeid) + if self.is_varsize(typeid): + length = (obj + self.varsize_offset_to_length(typeid)).signed[0] + size += self.varsize_item_sizes(typeid) * length + estimate = raw_malloc_usage(size_gc_header + size) + curr_heap_size += estimate + hdr = next + + # mark thinks on the mark stack and put their descendants onto the + # stack until the stack is empty while objects.non_empty(): #mark curr = objects.pop() -## print "object: ", curr + self.add_reachable_to_stack2(curr, objects, target_addr, source_addr) gc_info = curr - size_gc_header hdr = llmemory.cast_adr_to_ptr(gc_info, self.HDRPTR) if hdr.typeid & 1: continue - typeid = hdr.typeid >> 1 - offsets = self.offsets_to_gc_pointers(typeid) - i = 0 - while i < len(offsets): - pointer = curr + offsets[i] - objects.append(pointer.address[0]) - # ------------------------------------------------- - # begin difference from collect - if pointer.address[0] == target_addr: - pointer.address[0] == source_addr - # end difference from collect - # ------------------------------------------------- - i += 1 - if self.is_varsize(typeid): - offset = self.varsize_offset_to_variable_part( - typeid) - length = (curr + self.varsize_offset_to_length(typeid)).signed[0] - curr += offset - offsets = self.varsize_offsets_to_gcpointers_in_var_part(typeid) - itemlength = self.varsize_item_sizes(typeid) - i = 0 - while i < length: - item = curr + itemlength * i - j = 0 - while j < len(offsets): - objects.append((item + offsets[j]).address[0]) - # ------------------------------------------------- - # begin difference from collect - pointer = item + offsets[j] - if pointer.address[0] == target_addr: - pointer.address[0] == source_addr - ## end difference from collect - # ------------------------------------------------- - j += 1 - i += 1 hdr.typeid = hdr.typeid | 1 objects.delete() # also mark self.curpool @@ -612,15 +656,16 @@ hdr = llmemory.cast_adr_to_ptr(gc_info, self.HDRPTR) hdr.typeid = hdr.typeid | 1 - curr_heap_size = 0 - freed_size = 0 + # sweep: delete objects without del if they are not marked + # unmark objects without del that are marked firstpoolnode = lltype.malloc(self.POOLNODE, flavor='raw') firstpoolnode.linkedlist = self.malloced_objects firstpoolnode.nextnode = self.poolnodes prevpoolnode = lltype.nullptr(self.POOLNODE) poolnode = firstpoolnode while poolnode: #sweep - ppnext = lltype.direct_fieldptr(poolnode, 'linkedlist') + ppnext = llmemory.cast_ptr_to_adr(poolnode) + ppnext += llmemory.offsetof(self.POOLNODE, 'linkedlist') hdr = poolnode.linkedlist while hdr: #sweep typeid = hdr.typeid >> 1 @@ -633,14 +678,15 @@ estimate = raw_malloc_usage(size_gc_header + size) if hdr.typeid & 1: hdr.typeid = hdr.typeid & (~1) - ppnext[0] = hdr - ppnext = lltype.direct_fieldptr(hdr, 'next') + ppnext.address[0] = addr + ppnext = llmemory.cast_ptr_to_adr(hdr) + ppnext += llmemory.offsetof(self.HDR, 'next') curr_heap_size += estimate else: freed_size += estimate raw_free(addr) hdr = next - ppnext[0] = lltype.nullptr(self.HDR) + ppnext.address[0] = llmemory.NULL next = poolnode.nextnode if not poolnode.linkedlist and prevpoolnode: # completely empty node @@ -657,21 +703,43 @@ self.bytes_malloced_threshold = curr_heap_size end_time = time.time() self.total_collection_time += end_time - start_time - # warning, the following debug prints allocate memory to manipulate - # the strings! so they must be at the end if DEBUG_PRINT: - os.write(2, " malloced since previous collection: %s bytes\n" % - old_malloced) - os.write(2, " heap usage at start of collection: %s bytes\n" % - (self.heap_usage + old_malloced)) - os.write(2, " freed: %s bytes\n" % - freed_size) - os.write(2, " new heap usage: %s bytes\n" % - curr_heap_size) - os.write(2, " total time spent collecting: %s seconds\n" % - self.total_collection_time) + llop.debug_print(lltype.Void, + " malloced since previous collection:", + old_malloced, "bytes") + llop.debug_print(lltype.Void, + " heap usage at start of collection: ", + self.heap_usage + old_malloced, "bytes") + llop.debug_print(lltype.Void, + " freed: ", + freed_size, "bytes") + llop.debug_print(lltype.Void, + " new heap usage: ", + curr_heap_size, "bytes") + llop.debug_print(lltype.Void, + " total time spent collecting: ", + self.total_collection_time, "seconds") +## llop.debug_view(lltype.Void, self.malloced_objects, self.poolnodes, +## size_gc_header) assert self.heap_usage + old_malloced == curr_heap_size + freed_size + + # call finalizers if needed self.heap_usage = curr_heap_size + hdr = self.malloced_objects_with_finalizer + self.malloced_objects_with_finalizer = lltype.nullptr(self.HDR) + while hdr: + next = hdr.next + if hdr.typeid & 1: + hdr.next = self.malloced_objects_with_finalizer + self.malloced_objects_with_finalizer = hdr + hdr.typeid = hdr.typeid & (~1) + else: + obj = llmemory.cast_ptr_to_adr(hdr) + size_gc_header + finalizer = self.getfinalizer(hdr.typeid >> 1) + finalizer(obj) + hdr.next = self.malloced_objects + self.malloced_objects = hdr + hdr = next class SemiSpaceGC(GCBase): _alloc_flavor_ = "raw" From mwh at codespeak.net Mon May 22 01:13:37 2006 From: mwh at codespeak.net (mwh at codespeak.net) Date: Mon, 22 May 2006 01:13:37 +0200 (CEST) Subject: [pypy-svn] r27566 - in pypy/dist/pypy/rpython: . lltypesystem memory Message-ID: <20060521231337.DF35010077@code0.codespeak.net> Author: mwh Date: Mon May 22 01:13:34 2006 New Revision: 27566 Modified: pypy/dist/pypy/rpython/llinterp.py pypy/dist/pypy/rpython/lltypesystem/lloperation.py pypy/dist/pypy/rpython/memory/gc.py Log: a simple debug_pdb() command Modified: pypy/dist/pypy/rpython/llinterp.py ============================================================================== --- pypy/dist/pypy/rpython/llinterp.py (original) +++ pypy/dist/pypy/rpython/llinterp.py Mon May 22 01:13:34 2006 @@ -414,6 +414,10 @@ print arg, print + def op_debug_pdb(self, *ll_args): + import pdb + pdb.set_trace() + def op_keepalive(self, value): pass Modified: pypy/dist/pypy/rpython/lltypesystem/lloperation.py ============================================================================== --- pypy/dist/pypy/rpython/lltypesystem/lloperation.py (original) +++ pypy/dist/pypy/rpython/lltypesystem/lloperation.py Mon May 22 01:13:34 2006 @@ -357,6 +357,7 @@ # __________ debugging __________ 'debug_view': LLOp(), 'debug_print': LLOp(), + 'debug_pdb': LLOp(), } # __________ operations on PyObjects __________ Modified: pypy/dist/pypy/rpython/memory/gc.py ============================================================================== --- pypy/dist/pypy/rpython/memory/gc.py (original) +++ pypy/dist/pypy/rpython/memory/gc.py Mon May 22 01:13:34 2006 @@ -545,10 +545,9 @@ objects.append(pointer.address[0]) # ------------------------------------------------- # begin difference from collect - llop.debug_debug(lltype.Void, - pointer.address[0], target_addr, - pointer.address[0] == target_addr, - ) + llop.debug_pdb(lltype.Void, + pointer.address[0], target_addr, + pointer.address[0] == target_addr) if pointer.address[0] == target_addr: pointer.address[0] = source_addr # end difference from collect From mwh at codespeak.net Mon May 22 01:53:04 2006 From: mwh at codespeak.net (mwh at codespeak.net) Date: Mon, 22 May 2006 01:53:04 +0200 (CEST) Subject: [pypy-svn] r27567 - pypy/dist/pypy/rpython Message-ID: <20060521235304.E00C310076@code0.codespeak.net> Author: mwh Date: Mon May 22 01:53:03 2006 New Revision: 27567 Modified: pypy/dist/pypy/rpython/llinterp.py Log: add a print to the implementation of op_debug_pdb() Modified: pypy/dist/pypy/rpython/llinterp.py ============================================================================== --- pypy/dist/pypy/rpython/llinterp.py (original) +++ pypy/dist/pypy/rpython/llinterp.py Mon May 22 01:53:03 2006 @@ -415,6 +415,7 @@ print def op_debug_pdb(self, *ll_args): + print "entering pbb...", ll_args import pdb pdb.set_trace() From mwh at codespeak.net Mon May 22 01:53:47 2006 From: mwh at codespeak.net (mwh at codespeak.net) Date: Mon, 22 May 2006 01:53:47 +0200 (CEST) Subject: [pypy-svn] r27568 - pypy/dist/pypy/rpython/memory Message-ID: <20060521235347.A1A3610076@code0.codespeak.net> Author: mwh Date: Mon May 22 01:53:44 2006 New Revision: 27568 Modified: pypy/dist/pypy/rpython/memory/gc.py Log: there's no real reason we can't replace a root Modified: pypy/dist/pypy/rpython/memory/gc.py ============================================================================== --- pypy/dist/pypy/rpython/memory/gc.py (original) +++ pypy/dist/pypy/rpython/memory/gc.py Mon May 22 01:53:44 2006 @@ -545,9 +545,9 @@ objects.append(pointer.address[0]) # ------------------------------------------------- # begin difference from collect - llop.debug_pdb(lltype.Void, - pointer.address[0], target_addr, - pointer.address[0] == target_addr) +## llop.debug_pdb(lltype.Void, +## pointer.address[0], target_addr, +## pointer.address[0] == target_addr) if pointer.address[0] == target_addr: pointer.address[0] = source_addr # end difference from collect @@ -600,12 +600,6 @@ if curr == NULL: break # roots is a list of addresses to addresses: - # ------------------------------------------------- - # begin difference from collect - if curr.address[0] == target_addr: - raise RuntimeError("can't replace a root") - # end difference from collect - # ------------------------------------------------- objects.append(curr.address[0]) # the last sweep did not clear the mark bit of static roots, # since they are not in the malloced_objects list From mwh at codespeak.net Mon May 22 01:55:26 2006 From: mwh at codespeak.net (mwh at codespeak.net) Date: Mon, 22 May 2006 01:55:26 +0200 (CEST) Subject: [pypy-svn] r27569 - in pypy/dist/pypy/rpython: lltypesystem lltypesystem/test memory/test Message-ID: <20060521235526.A8C4710076@code0.codespeak.net> Author: mwh Date: Mon May 22 01:55:23 2006 New Revision: 27569 Modified: pypy/dist/pypy/rpython/lltypesystem/llmemory.py pypy/dist/pypy/rpython/lltypesystem/lltype.py pypy/dist/pypy/rpython/lltypesystem/test/test_llmemory.py pypy/dist/pypy/rpython/memory/test/test_transformed_gc.py Log: so my previous work on fakeaddress.__eq__ wasn't quite right as I didn't really understand how fakeaddess worked any more. fix + test. this was the last thing preventing test_x_become() from working, yay! Modified: pypy/dist/pypy/rpython/lltypesystem/llmemory.py ============================================================================== --- pypy/dist/pypy/rpython/lltypesystem/llmemory.py (original) +++ pypy/dist/pypy/rpython/lltypesystem/llmemory.py Mon May 22 01:55:23 2006 @@ -222,7 +222,8 @@ def __eq__(self, other): if self.__class__ is not other.__class__: return False - return self.array is other.array and self.index == other.index + return self.array._same_obj(other.array) and \ + self.index == other.index def type(self): return lltype.typeOf(self.array).TO.OF @@ -237,7 +238,7 @@ def __eq__(self, other): if self.__class__ is not other.__class__: return False - return self.array is other.array + return self.array._same_obj(other.array) def type(self): return lltype.Signed @@ -252,7 +253,8 @@ def __eq__(self, other): if self.__class__ is not other.__class__: return False - return self.struct is other.struct and self.fieldname == other.fieldname + return self.struct._same_obj(other.struct) and \ + self.fieldname == other.fieldname def type(self): return getattr(lltype.typeOf(self.struct).TO, self.fieldname) @@ -266,7 +268,7 @@ def __eq__(self, other): if self.__class__ is not other.__class__: return False - return self.ob is other.ob + return self.ob._same_obj(other.ob) def type(self): return lltype.typeOf(self.ob) Modified: pypy/dist/pypy/rpython/lltypesystem/lltype.py ============================================================================== --- pypy/dist/pypy/rpython/lltypesystem/lltype.py (original) +++ pypy/dist/pypy/rpython/lltypesystem/lltype.py Mon May 22 01:55:23 2006 @@ -851,6 +851,9 @@ def __ne__(self, other): return not (self == other) + def _same_obj(self, other): + return self._obj == other._obj + def __hash__(self): raise TypeError("pointer objects are not hashable") Modified: pypy/dist/pypy/rpython/lltypesystem/test/test_llmemory.py ============================================================================== --- pypy/dist/pypy/rpython/lltypesystem/test/test_llmemory.py (original) +++ pypy/dist/pypy/rpython/lltypesystem/test/test_llmemory.py Mon May 22 01:55:23 2006 @@ -101,7 +101,17 @@ assert a1s1 != as2 assert a1s1 != at assert as2 != at - + +def test_more_fakeaddress_equality(): + S = lltype.GcStruct('S', ('x', lltype.Signed)) + T = lltype.GcStruct('T', ('s', S)) + + t = lltype.malloc(T) + t.s.x = 1 + s = lltype.cast_pointer(lltype.Ptr(S), t) + + a_t, a_s = map(cast_ptr_to_adr, [s, t]) + assert a_t == a_s def test_cast_adr_to_int(): from pypy.rpython.memory.test.test_llinterpsim import interpret Modified: pypy/dist/pypy/rpython/memory/test/test_transformed_gc.py ============================================================================== --- pypy/dist/pypy/rpython/memory/test/test_transformed_gc.py (original) +++ pypy/dist/pypy/rpython/memory/test/test_transformed_gc.py Mon May 22 01:55:23 2006 @@ -507,7 +507,6 @@ GC_PARAMS = {'start_heap_size': 4096 } def test_x_become(self): - py.test.skip('fails less mysteriously') S = lltype.GcStruct("S", ('x', lltype.Signed)) def f(): x = lltype.malloc(S) From arigo at codespeak.net Mon May 22 02:13:02 2006 From: arigo at codespeak.net (arigo at codespeak.net) Date: Mon, 22 May 2006 02:13:02 +0200 (CEST) Subject: [pypy-svn] r27570 - in pypy/dist/pypy/rpython/lltypesystem: . test Message-ID: <20060522001302.8845610076@code0.codespeak.net> Author: arigo Date: Mon May 22 02:13:00 2006 New Revision: 27570 Modified: pypy/dist/pypy/rpython/lltypesystem/lltype.py pypy/dist/pypy/rpython/lltypesystem/test/test_lltype.py Log: (pedronis, arigo) A not extremely nice check-in that fixes equality between pointer to opaque objects. This is all getting very confusing with tons of methods everywhere... Modified: pypy/dist/pypy/rpython/lltypesystem/lltype.py ============================================================================== --- pypy/dist/pypy/rpython/lltypesystem/lltype.py (original) +++ pypy/dist/pypy/rpython/lltypesystem/lltype.py Mon May 22 02:13:00 2006 @@ -785,24 +785,9 @@ return p # primitive if not p: return None # null pointer - # - if p is an opaque pointer containing a normal Struct/GcStruct, - # unwrap it now - if isinstance(T.TO, OpaqueType) and hasattr(p._obj, 'container'): - T = Ptr(typeOf(p._obj.container)) - p = cast_opaque_ptr(T, p) - # - if p points to the first inlined substructure of a structure, - # make it point to the whole (larger) structure instead - container = p._obj - while True: - parent, index = parentlink(container) - if parent is None: - break - T = typeOf(parent) - if not isinstance(T, Struct) or T._first_struct()[0] != index: - break - container = parent + container = p._obj._normalizedcontainer() if container is not p._obj: - p = _ptr(Ptr(T), container, p._solid) + p = _ptr(Ptr(typeOf(container)), container, p._solid) return p @@ -1071,6 +1056,8 @@ return _ptr(Ptr(self._TYPE), self, True) def _as_obj(self): return self + def _normalizedcontainer(self): + return self class _parentable(_container): _kind = "?" @@ -1118,6 +1105,20 @@ __getstate__ = getstate_with_slots __setstate__ = setstate_with_slots + def _normalizedcontainer(self): + # if we are the first inlined substructure of a structure, + # return the whole (larger) structure instead + container = self + while True: + parent, index = parentlink(container) + if parent is None: + break + T = typeOf(parent) + if not isinstance(T, Struct) or T._first_struct()[0] != index: + break + container = parent + return container + def _struct_variety(flds, cache={}): flds = list(flds) flds.sort() @@ -1381,6 +1382,34 @@ def __str__(self): return "%s %s" % (self._TYPE.__name__, self._name) + def __eq__(self, other): + if self.__class__ is not other.__class__: + return False + if hasattr(self, 'container') and hasattr(other, 'container'): + obj1 = self.container._normalizedcontainer() + obj2 = other.container._normalizedcontainer() + return obj1 == obj2 + else: + return self is other + + def __ne__(self, other): + return not (self == other) + + def __hash__(self): + if hasattr(self, 'container'): + obj = self.container._normalizedcontainer() + return hash(obj) + else: + return _parentable.__hash__(self) + + def _normalizedcontainer(self): + # if we are an opaque containing a normal Struct/GcStruct, + # unwrap it + if hasattr(self, 'container'): + return self.container._normalizedcontainer() + else: + return _parentable._normalizedcontainer(self) + class _pyobject(Hashable, _container): __slots__ = [] # or we get in trouble with pickling Modified: pypy/dist/pypy/rpython/lltypesystem/test/test_lltype.py ============================================================================== --- pypy/dist/pypy/rpython/lltypesystem/test/test_lltype.py (original) +++ pypy/dist/pypy/rpython/lltypesystem/test/test_lltype.py Mon May 22 02:13:00 2006 @@ -472,6 +472,19 @@ S2 = Struct('S2', ('z', Signed)) py.test.raises(InvalidCast, "cast_opaque_ptr(Ptr(S2), o1)") + BIG = GcStruct('BIG', ('s', S)) + UNRELATED = GcStruct('UNRELATED') + big = malloc(BIG) + unrelated = malloc(UNRELATED) + p1 = cast_opaque_ptr(Ptr(O), big) + p2 = cast_opaque_ptr(Ptr(O), big) + assert p1 == p2 + p3 = cast_opaque_ptr(Ptr(O), big.s) + assert p1 == p3 + p4 = cast_opaque_ptr(Ptr(O), unrelated) + assert p1 != p4 + assert p3 != p4 + def test_is_atomic(): U = Struct('inlined', ('z', Signed)) A = Ptr(RuntimeTypeInfo) From njriley at codespeak.net Mon May 22 03:21:50 2006 From: njriley at codespeak.net (njriley at codespeak.net) Date: Mon, 22 May 2006 03:21:50 +0200 (CEST) Subject: [pypy-svn] r27571 - pypy/branch/njriley-trans/pypy/translator/c/src Message-ID: <20060522012150.8109010072@code0.codespeak.net> Author: njriley Date: Mon May 22 03:21:40 2006 New Revision: 27571 Modified: pypy/branch/njriley-trans/pypy/translator/c/src/ll_trans.h Log: Use __thread-style TLS for transaction pause state. Modified: pypy/branch/njriley-trans/pypy/translator/c/src/ll_trans.h ============================================================================== --- pypy/branch/njriley-trans/pypy/translator/c/src/ll_trans.h (original) +++ pypy/branch/njriley-trans/pypy/translator/c/src/ll_trans.h Mon May 22 03:21:40 2006 @@ -55,29 +55,18 @@ XACT_UNPAUSE(pause_state); } -/* XXX deliberately not RPyThreadTLS here => dependency problems */ -static pthread_key_t pause_state_key = 0; +static __thread int pause_state; void LL_trans_pause(void) { - int *pause_state; - if (pause_state_key == 0) - assert(pthread_key_create(&pause_state_key, free) == 0); - pause_state = (int *)pthread_getspecific(pause_state_key); - if (pause_state == NULL) { - pause_state = malloc(sizeof(int)); - assert(pthread_setspecific(pause_state_key, pause_state) == 0); - } - XACT_PAUSE(*pause_state); + XACT_PAUSE(pause_state); } void LL_trans_unpause(void) { - int *pause_state = (int *)pthread_getspecific(pause_state_key); - assert(pause_state != NULL); - XACT_UNPAUSE(*pause_state); + XACT_UNPAUSE(pause_state); } void @@ -94,16 +83,6 @@ LL_trans_enable(void) { int ret_val; - // XXX HACK HACK HACK, 1024 is first thread id - if (pthread_self() == 1024) { - static int suspended = 0; - if (suspended) - return; - suspended = 1; - pid_t pid = getpid(); - fprintf(stderr, "LL_trans_enable: suspending, pid is %d\n", pid); - kill(pid, SIGSTOP); - } ret_val = enable_transactions(); if (ret_val != 0) { printf("Load transactional memory module and press return\n"); From ericvrp at codespeak.net Mon May 22 12:09:36 2006 From: ericvrp at codespeak.net (ericvrp at codespeak.net) Date: Mon, 22 May 2006 12:09:36 +0200 (CEST) Subject: [pypy-svn] r27591 - pypy/extradoc/sprintinfo/ddorf2006 Message-ID: <20060522100936.817ED10075@code0.codespeak.net> Author: ericvrp Date: Mon May 22 12:09:29 2006 New Revision: 27591 Modified: pypy/extradoc/sprintinfo/ddorf2006/people.txt Log: I can not make it at the beginning of the sprint after all. Will arrive on the evening of the 6th and return early during the morning of the 8th already. Modified: pypy/extradoc/sprintinfo/ddorf2006/people.txt ============================================================================== --- pypy/extradoc/sprintinfo/ddorf2006/people.txt (original) +++ pypy/extradoc/sprintinfo/ddorf2006/people.txt Mon May 22 12:09:29 2006 @@ -12,7 +12,7 @@ Armin Rigo ? private Holger Krekel 1st-9th ? Carl Friedrich Bolz nope :-) private -Eric van Riet Paap 2nd-4th + 7th? ? +Eric van Riet Paap 6th - 8th private Maciej Fijalkowski 3rd-9th cfbolz Anders Chrigstroem 1st - 9th ? Samuele Pedroni 1st - 9th ? From ale at codespeak.net Mon May 22 13:43:09 2006 From: ale at codespeak.net (ale at codespeak.net) Date: Mon, 22 May 2006 13:43:09 +0200 (CEST) Subject: [pypy-svn] r27594 - in pypy/dist/pypy/lib/pyontology: . test Message-ID: <20060522114309.44DC210071@code0.codespeak.net> Author: ale Date: Mon May 22 13:43:08 2006 New Revision: 27594 Modified: pypy/dist/pypy/lib/pyontology/pyontology.py pypy/dist/pypy/lib/pyontology/test/test_ontology.py Log: Support for OWL:imports Modified: pypy/dist/pypy/lib/pyontology/pyontology.py ============================================================================== --- pypy/dist/pypy/lib/pyontology/pyontology.py (original) +++ pypy/dist/pypy/lib/pyontology/pyontology.py Mon May 22 13:43:08 2006 @@ -495,10 +495,11 @@ def complementOf(self, s, var): # add constraint of not var - # TODO: implementthis for OWL DL + # i.e. the extension of s shall contain all individuals not in var + # We need to know all elements and subtract the elements of var ## avar = self.make_var(ClassDomain, var) ## svar = self.make_var(ClassDomain, s) - pass + pass def oneOf(self, s, var): var = self.flatten_rdf_list(var) @@ -590,8 +591,8 @@ cls_name = self.make_var(ClassDomain, cls) prop = self.variables[svar].property self.variables[svar].TBox[prop] = {'Cardinality': [( '<', int(var))]} - formula = "not isinstance(%s[0], self.variables[%s]) or len(%s[1]) < int(%s)" %(prop, cls_name, prop, var) - constrain = Expression([prop, cls_name, prop, var], formula) + formula = "len(%s[1]) < int(%s)" %(prop, var) + constrain = Expression([prop], formula) self.constraints.append(constrain) for cls,vals in self.variables[prop].getValuesPrKey(): @@ -667,8 +668,13 @@ # ----------------- ---------------- def imports(self, s, var): - # PP TODO: implement this - pass + # Get the url + url = var + # add the triples to the graph + tmp = Graph() + tmp.load(url) + for trip in tmp.triples((None,)*3): + self.add(trip) def sameAs(self, s, var): s_var = self.make_var(Thing, s) Modified: pypy/dist/pypy/lib/pyontology/test/test_ontology.py ============================================================================== --- pypy/dist/pypy/lib/pyontology/test/test_ontology.py (original) +++ pypy/dist/pypy/lib/pyontology/test/test_ontology.py Mon May 22 13:43:08 2006 @@ -149,10 +149,10 @@ O = Ontology() sub = URIRef('a') obj = URIRef('b') - O.variables['b_'] = fd([1,2,3,4]) + O.variables['b_'] = ClassDomain(values=[1,2,3,4]) O.range(sub, obj) obj = URIRef('c') - O.variables['c_'] = fd([3,4,5,6]) + O.variables['c_'] = ClassDomain(values=[3,4,5,6]) O.range(sub, obj) sub = URIRef('a') pred = URIRef('type') @@ -577,4 +577,10 @@ O = Ontology() O.add_file('approved/allValuesfrom/premises002.rdf') O.add_file('approved/allValuesfrom/nonconclusions002.rdf') - assert 1 \ No newline at end of file + +def test_import(): + O = Ontology() + s = URIRef('s') + O.imports(s,URIRef('http://www.w3.org/2002/03owlt/imports/support001-A')) + print list(O.graph.triples((None,)*3)) + assert 0 \ No newline at end of file From arigo at codespeak.net Mon May 22 16:59:01 2006 From: arigo at codespeak.net (arigo at codespeak.net) Date: Mon, 22 May 2006 16:59:01 +0200 (CEST) Subject: [pypy-svn] r27603 - pypy/dist/pypy/doc/discussion Message-ID: <20060522145901.3D8A110074@code0.codespeak.net> Author: arigo Date: Mon May 22 16:59:00 2006 New Revision: 27603 Added: pypy/dist/pypy/doc/discussion/security-ideas.html Log: Draft notes following an inspiring security-in-Haskell talk I attended. Added: pypy/dist/pypy/doc/discussion/security-ideas.html ============================================================================== --- (empty file) +++ pypy/dist/pypy/doc/discussion/security-ideas.html Mon May 22 16:59:00 2006 @@ -0,0 +1,296 @@ + + + + + + +Security ideas + + +
+

Security ideas

+

These are some notes I (Armin) took after a talk at Chalmers by Steve +Zdancewic: "Encoding Information Flow in Haskell". That talk was +presenting a pure Haskell approach with monad-like constructions; I +think that the approach translates well to PyPy at the level of RPython.

+
+

The problem

+

The problem that we try to solve here is: how to give the programmer a +way to write programs that are easily checked to be "secure", in the +sense that bugs shouldn't allow confidential information to be +unexpectedly leaked. This is not security as in defeating actively +malicious attackers.

+
+
+

Example

+

Let's suppose that we want to write a telnet-based application for a +bidding system. We want normal users to be able to log in with their +username and password, and place bids (i.e. type in an amount of money). +The server should record the highest bid so far but not allow users to +see that number. Additionally, the administrator should be able to log +in with his own password and see the highest bid. The basic program:

+
+def mainloop():
+    while True:
+        username = raw_input()
+        password = raw_input()
+        user = authenticate(username, password)
+        if user == 'guest':
+            serve_guest()
+        elif user == 'admin':
+            serve_admin()
+
+def serve_guest():
+    global highest_bid
+    print "Enter your bid:"
+    n = int(raw_input())
+    if n > highest_bid:     #
+        highest_bid = n     #
+    print "Thank you"
+
+def serve_admin():
+    print "Highest big is:", highest_bid
+
+

The goal is to make this program more secure by declaring and enforcing +the following properties: first, the guest code is allowed to manipulate +the highest_bid, as in the lines marked with #, but these lines must +not leak back the highest_bid in a form visible to the guest user; +second, the printing in serve_admin() must only be allowed if the user +that logged in is really the administrator (e.g. catch bugs like +accidentally swapping the serve_guest() and serve_admin() calls in +mainloop()).

+
+
+

Preventing leak of information in guest code: 1st try

+

The basic technique to prevent leaks is to attach "confidentiality +level" tags to objects. In this example, the highest_bid int object +would be tagged with label="secret", e.g. by being initialized as:

+
+highest_bid = tag(0, label="secret")
+
+

At first, we can think about an object space where all objects have such +a label, and the label propagates to operations between objects: for +example, code like highest_bid += 1 would produce a new int object +with again label="secret".

+

Where this approach doesn't work is with if/else or loops. In the above +example, we do:

+
+if n > highest_bid:
+    ...
+
+

However, by the object space rules introduced above, the result of the +comparison is a "secret" bool objects. This means that the guest code +cannot know if it is True or False, and so the PyPy interpreter has no +clue if it must following the then or else branch of the if. +So the guest code could do highest_bid += 1 and probably even +highest_bid = max(highest_bid, n) if max() is a clever enough +built-in function, but clearly this approach doesn't work well for more +complicated computations that we would like to perform at this point.

+

There might be very cool possible ideas to solve this with doing some +kind of just-in-time flow object space analysis. However, here is a +possibly more practical approach. Let's forget about the object space +tricks and start again. (See Related work for why the object space +approach doesn't work too well.)

+
+
+

Preventing leak of information in guest code with the annotator instead

+

Suppose that the program runs on top of CPython and not necessarily +PyPy. We will only need PyPy's annotator. The idea is to mark the code +that manipulates highest_bid explicitly, and make it RPython in the +sense that we can take its flow space and follow the calls (we don't +care about the precise types here -- we will use different annotations). +Note that only the bits that manipulates the secret values needs to be +RPython. Example:

+
+# on top of CPython, 'hidden' is a type that hides a value without
+# giving any way to normal programs to access it, so the program
+# cannot do anything with 'highest_bid'
+
+highest_bid = hidden(0, label="secure")
+
+def enter_bid(n):
+    if n > highest_bid.value:
+        highest_bid.value = n
+
+enter_bid = secure(enter_bid)
+
+def serve_guest():
+    print "Enter your bid:"
+    n = int(raw_input())
+    enter_bid(n)
+    print "Thank you"
+
+

The point is that the expression highest_bid.value raises a +SecurityException when run normally: it is not allowed to read this +value. The secure() decorator uses the annotator on the enter_bid() +function, with special annotations that I will describe shortly. Then +secure() returns a "compiled" version of enter_bid. The compiled +version is checked to satisfy the security constrains, and it contains +special code that then enables the highest_bid.value to work.

+

The annotations propagated by secure() are SomeSecurityLevel +annotations. Normal constants are propagated as +SomeSecurityLevel("public"). The highest_bid.value returns the +annotation SomeSecurityLevel("secret"), which is the label of the +constant highest_bid hidden object. We define operations between +two SomeSecurityLevels to return a SomeSecurityLevel which is the max of +the secret levels of the operands.

+

The key point is that secure() checks that the return value is +SomeSecurityLevel("public"). It also checks that only +SomeSecurityLevel("public") values are stored e.g. in global data +structures.

+

In this way, any CPython code like serve_guest() can safely call +enter_bid(n). There is no way to leak information about the current +highest bid back out of the compiled enter_bid().

+
+
+

Declassification

+

Now there must be a controlled way to leak the highest_bid value, +otherwise it is impossible even for the admin to read it. Note that +serve_admin(), which prints highest_bid, is considered to "leak" this +value because it is an input-output, i.e. it escapes the program. This +is a leak that we actually want -- the terminology is that serve_admin() +must "declassify" the value.

+

To do this, there is a capability-like model that is easy to implement +for us. Let us modify the main loop as follows:

+
+def mainloop():
+    while True:
+        username = raw_input()
+        password = raw_input()
+        user, priviledge_token = authenticate(username, password)
+        if user == 'guest':
+            serve_guest()
+        elif user == 'admin':
+            serve_admin(priviledge_token)
+        del priviledge_token   # make sure nobody else uses it
+
+

The idea is that the authenticate() function (shown later) also returns +a "token" object. This is a normal Python object, but it should not be +possible for normal Python code to instantiate such an object manually. +In this example, authenticate() returns a priviledge("public") for +guests, and a priviledge("secret") for admins. Now -- and this is +the insecure part of this scheme, but it is relatively easy to control +-- the programmer must make sure that these priviledge_token objects +don't go to unexpected places, particularly the "secret" one. They work +like capabilities: having a reference to them allows parts of the +program to see secret information, of a confidentiality level up to the +one corresponding to the token.

+

Now we modify serve_admin() as follows:

+
+
+
def serve_admin(token):
+
print "Highest big is:", declassify(highest_bid, token=token)
+
+
+

The declassify() function reads the value if the "token" is priviledged +enough, and raises an exception otherwise.

+

What are we protecting here? The fact that we need the administrator +token in order to see the highest bid. If by mistake we swap the +serve_guest() and serve_admin() lines in mainloop(), then what occurs is +that serve_admin() would be called with the guest token. Then +declassify() would fail. If we assume that authenticate() is not buggy, +then the rest of the program is safe from leak bugs.

+

There are another variants of declassify() that are convenient. For +example, in the RPython parts of the code, declassify() can be used to +control more precisely at which confidentiality levels we want which +values, if there are more than just two such levels. The "token" +argument could also be implicit in RPython parts, meaning "use the +current level"; normal non-RPython code always runs at "public" level, +but RPython functions could run with higher current levels, e.g. if they +are called with a "token=..." argument.

+

(Do not confuse this with what enter_bid() does: enter_bid() runs at the +public level all along. It is ok for it to compute with, and even +modify, the highest_bid.value. The point of enter_bid() was that by +being an RPython function the annotator can make sure that the value, or +even anything that gives a hint about the value, cannot possibly escape +from the function.)

+

It is also useful to have "globally trusted" administrator-level RPython +functions that always run at a higher level than the caller, a bit like +Unix programs with the "suid" bit. If we set aside the consideration +that it should not be possible to make new "suid" functions too easily, +then we could define the authenticate() function of our server example +as follows:

+
+def authenticate(username, password):
+    database = {('guest', 'abc'): priviledge("public"),
+                ('admin', '123'): priviledge("secret")}
+    token_obj = database[username, password]
+    return username, declassify(token_obj, target_level="public")
+
+authenticate = secure(authenticate, suid="secret")
+
+

The "suid" argument makes the compiled function run on level "secret" +even if the caller is "public" or plain CPython code. The declassify() +in the function is allowed because of the current level of "secret". +Note that the function returns a "public" tuple -- the username is +public, and the token_obj is declassified to public. This is the +property that allows CPython code to call it.

+

Of course, like a Unix suid program the authenticate() function could be +buggy and leak information, but like suid programs it is small enough +for us to feel that it is secure just by staring at the code.

+

An alternative to the suid approach is to play with closures, e.g.:

+
+def setup():
+    #initialize new levels -- this cannot be used to access existing levels
+    public_level = create_new_priviledge("public")
+    secret_level = create_new_priviledge("secret")
+
+    database = {('guest', 'abc'): public_level,
+                ('admin', '123'): secret_level}
+
+    def authenticate(username, password):
+        token_obj = database[username, password]
+        return username, declassify(token_obj, target_level="public",
+                                               token=secret_level)
+
+    return secure(authenticate)
+
+authenticate = setup()
+
+

In this approach, declassify() works because it has access to the +secret_level token. We still need to make authenticate() a secure() +compiled function to hide the database and the secret_level more +carefully; otherwise, code could accidentally find them by inspecting +the traceback of the KeyError exception if the username or password is +invalid. Also, secure() will check for us that authenticate() indeed +returns a "public" tuple.

+

This basic model is easy to extend in various directions. For example +secure() RPython functions should be allowed to return non-public +results -- but then they have to be called either with an appropriate +"token=..." keyword, or else they return hidden objects again. They +could also be used directly from other RPython functions, in which the +level of what they return is propagated.

+
+
+

Related work

+

What I'm describing here is nothing more than an adaptation of existing +techniques to RPython.

+

It is noteworthy to mention at this point why the object space approach +doesn't work as well as we could first expect. The distinction between +static checking and dynamic checking (with labels only attached to +values) seems to be well known; also, it seems to be well known that the +latter is too coarse in practice. The problem is about branching and +looping. From the object space' point of view it is quite hard to know +what a newly computed value really depends on. Basically, it is +difficult to do better than: after is_true() has been called on a secret +object, then we must assume that all objects created are also secret +because they could depend in some way on the truth-value of the previous +secret object.

+

The idea to dynamically use static analysis is the key new idea +presented by Steve Zdancewic in his talk. You can have small controlled +RPython parts of the program that must pass through a static analysis, +and we only need to check dynamically that some input conditions are +satisfied when other parts of the program call the RPython parts. +Previous research was mostly about designing languages that are +completely statically checked at compile-time. The delicate part is to +get the static/dynamic mixture right so that even indirect leaks are not +possible -- e.g. leaks that would occur from calling functions with +strange arguments to provoke exceptions, and where the presence of the +exception or not would be information in itself. This approach seems to +do that reliably. (Of course, at the talk many people including the +speaker were wondering about ways to move more of the checking at +compile-time, but Python people won't have such worries :-)

+
+
+ + From arigo at codespeak.net Mon May 22 17:01:50 2006 From: arigo at codespeak.net (arigo at codespeak.net) Date: Mon, 22 May 2006 17:01:50 +0200 (CEST) Subject: [pypy-svn] r27604 - pypy/dist/pypy/doc/discussion Message-ID: <20060522150150.A71E21006E@code0.codespeak.net> Author: arigo Date: Mon May 22 17:01:49 2006 New Revision: 27604 Added: pypy/dist/pypy/doc/discussion/security-ideas.txt (contents, props changed) Removed: pypy/dist/pypy/doc/discussion/security-ideas.html Log: Of course, I meant to check in the txt (thanks Carl) Added: pypy/dist/pypy/doc/discussion/security-ideas.txt ============================================================================== --- (empty file) +++ pypy/dist/pypy/doc/discussion/security-ideas.txt Mon May 22 17:01:49 2006 @@ -0,0 +1,312 @@ +============== +Security ideas +============== + +These are some notes I (Armin) took after a talk at Chalmers by Steve +Zdancewic: "Encoding Information Flow in Haskell". That talk was +presenting a pure Haskell approach with monad-like constructions; I +think that the approach translates well to PyPy at the level of RPython. + + +The problem +----------- + +The problem that we try to solve here is: how to give the programmer a +way to write programs that are easily checked to be "secure", in the +sense that bugs shouldn't allow confidential information to be +unexpectedly leaked. This is not security as in defeating actively +malicious attackers. + + +Example +------- + +Let's suppose that we want to write a telnet-based application for a +bidding system. We want normal users to be able to log in with their +username and password, and place bids (i.e. type in an amount of money). +The server should record the highest bid so far but not allow users to +see that number. Additionally, the administrator should be able to log +in with his own password and see the highest bid. The basic program:: + + def mainloop(): + while True: + username = raw_input() + password = raw_input() + user = authenticate(username, password) + if user == 'guest': + serve_guest() + elif user == 'admin': + serve_admin() + + def serve_guest(): + global highest_bid + print "Enter your bid:" + n = int(raw_input()) + if n > highest_bid: # + highest_bid = n # + print "Thank you" + + def serve_admin(): + print "Highest big is:", highest_bid + +The goal is to make this program more secure by declaring and enforcing +the following properties: first, the guest code is allowed to manipulate +the highest_bid, as in the lines marked with ``#``, but these lines must +not leak back the highest_bid in a form visible to the guest user; +second, the printing in serve_admin() must only be allowed if the user +that logged in is really the administrator (e.g. catch bugs like +accidentally swapping the serve_guest() and serve_admin() calls in +mainloop()). + + +Preventing leak of information in guest code: 1st try +----------------------------------------------------- + +The basic technique to prevent leaks is to attach "confidentiality +level" tags to objects. In this example, the highest_bid int object +would be tagged with label="secret", e.g. by being initialized as:: + + highest_bid = tag(0, label="secret") + +At first, we can think about an object space where all objects have such +a label, and the label propagates to operations between objects: for +example, code like ``highest_bid += 1`` would produce a new int object +with again label="secret". + +Where this approach doesn't work is with if/else or loops. In the above +example, we do:: + + if n > highest_bid: + ... + +However, by the object space rules introduced above, the result of the +comparison is a "secret" bool objects. This means that the guest code +cannot know if it is True or False, and so the PyPy interpreter has no +clue if it must following the ``then`` or ``else`` branch of the ``if``. +So the guest code could do ``highest_bid += 1`` and probably even +``highest_bid = max(highest_bid, n)`` if max() is a clever enough +built-in function, but clearly this approach doesn't work well for more +complicated computations that we would like to perform at this point. + +There might be very cool possible ideas to solve this with doing some +kind of just-in-time flow object space analysis. However, here is a +possibly more practical approach. Let's forget about the object space +tricks and start again. (See `Related work`_ for why the object space +approach doesn't work too well.) + + +Preventing leak of information in guest code with the annotator instead +----------------------------------------------------------------------- + +Suppose that the program runs on top of CPython and not necessarily +PyPy. We will only need PyPy's annotator. The idea is to mark the code +that manipulates highest_bid explicitly, and make it RPython in the +sense that we can take its flow space and follow the calls (we don't +care about the precise types here -- we will use different annotations). +Note that only the bits that manipulates the secret values needs to be +RPython. Example:: + + # on top of CPython, 'hidden' is a type that hides a value without + # giving any way to normal programs to access it, so the program + # cannot do anything with 'highest_bid' + + highest_bid = hidden(0, label="secure") + + def enter_bid(n): + if n > highest_bid.value: + highest_bid.value = n + + enter_bid = secure(enter_bid) + + def serve_guest(): + print "Enter your bid:" + n = int(raw_input()) + enter_bid(n) + print "Thank you" + +The point is that the expression ``highest_bid.value`` raises a +SecurityException when run normally: it is not allowed to read this +value. The secure() decorator uses the annotator on the enter_bid() +function, with special annotations that I will describe shortly. Then +secure() returns a "compiled" version of enter_bid. The compiled +version is checked to satisfy the security constrains, and it contains +special code that then enables the ``highest_bid.value`` to work. + +The annotations propagated by secure() are ``SomeSecurityLevel`` +annotations. Normal constants are propagated as +SomeSecurityLevel("public"). The ``highest_bid.value`` returns the +annotation SomeSecurityLevel("secret"), which is the label of the +constant ``highest_bid`` hidden object. We define operations between +two SomeSecurityLevels to return a SomeSecurityLevel which is the max of +the secret levels of the operands. + +The key point is that secure() checks that the return value is +SomeSecurityLevel("public"). It also checks that only +SomeSecurityLevel("public") values are stored e.g. in global data +structures. + +In this way, any CPython code like serve_guest() can safely call +``enter_bid(n)``. There is no way to leak information about the current +highest bid back out of the compiled enter_bid(). + + +Declassification +---------------- + +Now there must be a controlled way to leak the highest_bid value, +otherwise it is impossible even for the admin to read it. Note that +serve_admin(), which prints highest_bid, is considered to "leak" this +value because it is an input-output, i.e. it escapes the program. This +is a leak that we actually want -- the terminology is that serve_admin() +must "declassify" the value. + +To do this, there is a capability-like model that is easy to implement +for us. Let us modify the main loop as follows:: + + def mainloop(): + while True: + username = raw_input() + password = raw_input() + user, priviledge_token = authenticate(username, password) + if user == 'guest': + serve_guest() + elif user == 'admin': + serve_admin(priviledge_token) + del priviledge_token # make sure nobody else uses it + +The idea is that the authenticate() function (shown later) also returns +a "token" object. This is a normal Python object, but it should not be +possible for normal Python code to instantiate such an object manually. +In this example, authenticate() returns a ``priviledge("public")`` for +guests, and a ``priviledge("secret")`` for admins. Now -- and this is +the insecure part of this scheme, but it is relatively easy to control +-- the programmer must make sure that these priviledge_token objects +don't go to unexpected places, particularly the "secret" one. They work +like capabilities: having a reference to them allows parts of the +program to see secret information, of a confidentiality level up to the +one corresponding to the token. + +Now we modify serve_admin() as follows: + + def serve_admin(token): + print "Highest big is:", declassify(highest_bid, token=token) + +The declassify() function reads the value if the "token" is priviledged +enough, and raises an exception otherwise. + +What are we protecting here? The fact that we need the administrator +token in order to see the highest bid. If by mistake we swap the +serve_guest() and serve_admin() lines in mainloop(), then what occurs is +that serve_admin() would be called with the guest token. Then +declassify() would fail. If we assume that authenticate() is not buggy, +then the rest of the program is safe from leak bugs. + +There are another variants of declassify() that are convenient. For +example, in the RPython parts of the code, declassify() can be used to +control more precisely at which confidentiality levels we want which +values, if there are more than just two such levels. The "token" +argument could also be implicit in RPython parts, meaning "use the +current level"; normal non-RPython code always runs at "public" level, +but RPython functions could run with higher current levels, e.g. if they +are called with a "token=..." argument. + +(Do not confuse this with what enter_bid() does: enter_bid() runs at the +public level all along. It is ok for it to compute with, and even +modify, the highest_bid.value. The point of enter_bid() was that by +being an RPython function the annotator can make sure that the value, or +even anything that gives a hint about the value, cannot possibly escape +from the function.) + +It is also useful to have "globally trusted" administrator-level RPython +functions that always run at a higher level than the caller, a bit like +Unix programs with the "suid" bit. If we set aside the consideration +that it should not be possible to make new "suid" functions too easily, +then we could define the authenticate() function of our server example +as follows:: + + def authenticate(username, password): + database = {('guest', 'abc'): priviledge("public"), + ('admin', '123'): priviledge("secret")} + token_obj = database[username, password] + return username, declassify(token_obj, target_level="public") + + authenticate = secure(authenticate, suid="secret") + +The "suid" argument makes the compiled function run on level "secret" +even if the caller is "public" or plain CPython code. The declassify() +in the function is allowed because of the current level of "secret". +Note that the function returns a "public" tuple -- the username is +public, and the token_obj is declassified to public. This is the +property that allows CPython code to call it. + +Of course, like a Unix suid program the authenticate() function could be +buggy and leak information, but like suid programs it is small enough +for us to feel that it is secure just by staring at the code. + +An alternative to the suid approach is to play with closures, e.g.:: + + def setup(): + #initialize new levels -- this cannot be used to access existing levels + public_level = create_new_priviledge("public") + secret_level = create_new_priviledge("secret") + + database = {('guest', 'abc'): public_level, + ('admin', '123'): secret_level} + + def authenticate(username, password): + token_obj = database[username, password] + return username, declassify(token_obj, target_level="public", + token=secret_level) + + return secure(authenticate) + + authenticate = setup() + +In this approach, declassify() works because it has access to the +secret_level token. We still need to make authenticate() a secure() +compiled function to hide the database and the secret_level more +carefully; otherwise, code could accidentally find them by inspecting +the traceback of the KeyError exception if the username or password is +invalid. Also, secure() will check for us that authenticate() indeed +returns a "public" tuple. + +This basic model is easy to extend in various directions. For example +secure() RPython functions should be allowed to return non-public +results -- but then they have to be called either with an appropriate +"token=..." keyword, or else they return hidden objects again. They +could also be used directly from other RPython functions, in which the +level of what they return is propagated. + + +Related work +------------ + +What I'm describing here is nothing more than an adaptation of existing +techniques to RPython. + +It is noteworthy to mention at this point why the object space approach +doesn't work as well as we could first expect. The distinction between +static checking and dynamic checking (with labels only attached to +values) seems to be well known; also, it seems to be well known that the +latter is too coarse in practice. The problem is about branching and +looping. From the object space' point of view it is quite hard to know +what a newly computed value really depends on. Basically, it is +difficult to do better than: after is_true() has been called on a secret +object, then we must assume that all objects created are also secret +because they could depend in some way on the truth-value of the previous +secret object. + +The idea to dynamically use static analysis is the key new idea +presented by Steve Zdancewic in his talk. You can have small controlled +RPython parts of the program that must pass through a static analysis, +and we only need to check dynamically that some input conditions are +satisfied when other parts of the program call the RPython parts. +Previous research was mostly about designing languages that are +completely statically checked at compile-time. The delicate part is to +get the static/dynamic mixture right so that even indirect leaks are not +possible -- e.g. leaks that would occur from calling functions with +strange arguments to provoke exceptions, and where the presence of the +exception or not would be information in itself. This approach seems to +do that reliably. (Of course, at the talk many people including the +speaker were wondering about ways to move more of the checking at +compile-time, but Python people won't have such worries :-) From cfbolz at codespeak.net Mon May 22 17:29:07 2006 From: cfbolz at codespeak.net (cfbolz at codespeak.net) Date: Mon, 22 May 2006 17:29:07 +0200 (CEST) Subject: [pypy-svn] r27605 - in pypy/dist/pypy/rpython/memory: . test Message-ID: <20060522152907.C533A10074@code0.codespeak.net> Author: cfbolz Date: Mon May 22 17:29:06 2006 New Revision: 27605 Modified: pypy/dist/pypy/rpython/memory/gc.py pypy/dist/pypy/rpython/memory/test/test_transformed_gc.py Log: try to make recursive calls to collect not crash. does not work with stackless, so just prevent those calls :-(. some tests. Modified: pypy/dist/pypy/rpython/memory/gc.py ============================================================================== --- pypy/dist/pypy/rpython/memory/gc.py (original) +++ pypy/dist/pypy/rpython/memory/gc.py Mon May 22 17:29:06 2006 @@ -153,6 +153,7 @@ # was already freed. The objects in 'malloced_objects' are not # found via 'poolnodes'. self.poolnodes = lltype.nullptr(self.POOLNODE) + self.collect_in_progress = False def malloc(self, typeid, length=0): size = self.fixed_size(typeid) @@ -217,9 +218,14 @@ # call __del__, move the object to the list of object-without-del import time from pypy.rpython.lltypesystem.lloperation import llop + # XXX the following two lines should not be there, but without them + # there is a strange crash in decodestate when using stackless :-( + if self.collect_in_progress: + return if DEBUG_PRINT: llop.debug_print(lltype.Void, 'collecting...') start_time = time.time() + self.collect_in_progress = True roots = self.get_roots() size_gc_header = self.gcheaderbuilder.size_gc_header ## llop.debug_view(lltype.Void, self.malloced_objects, self.poolnodes, @@ -323,6 +329,7 @@ self.malloced_objects = firstpoolnode.linkedlist self.poolnodes = firstpoolnode.nextnode lltype.free(firstpoolnode, flavor='raw') + #llop.debug_view(lltype.Void, self.malloced_objects, self.malloced_objects_with_finalizer, size_gc_header) if curr_heap_size > self.bytes_malloced_threshold: self.bytes_malloced_threshold = curr_heap_size @@ -348,23 +355,49 @@ ## size_gc_header) assert self.heap_usage + old_malloced == curr_heap_size + freed_size - # call finalizers if needed self.heap_usage = curr_heap_size hdr = self.malloced_objects_with_finalizer self.malloced_objects_with_finalizer = lltype.nullptr(self.HDR) + last = lltype.nullptr(self.HDR) while hdr: next = hdr.next if hdr.typeid & 1: - hdr.next = self.malloced_objects_with_finalizer - self.malloced_objects_with_finalizer = hdr + hdr.next = lltype.nullptr(self.HDR) + if not self.malloced_objects_with_finalizer: + self.malloced_objects_with_finalizer = hdr + else: + last.next = hdr hdr.typeid = hdr.typeid & (~1) + last = hdr else: obj = llmemory.cast_ptr_to_adr(hdr) + size_gc_header finalizer = self.getfinalizer(hdr.typeid >> 1) - finalizer(obj) + # make malloced_objects_with_finalizer consistent + # for the sake of a possible collection caused by finalizer + if not self.malloced_objects_with_finalizer: + self.malloced_objects_with_finalizer = next + else: + last.next = next hdr.next = self.malloced_objects self.malloced_objects = hdr + #llop.debug_view(lltype.Void, self.malloced_objects, self.malloced_objects_with_finalizer, size_gc_header) + finalizer(obj) + if not self.collect_in_progress: # another collection was caused? + return + if not last: + if self.malloced_objects_with_finalizer == next: + self.malloced_objects_with_finalizer = lltype.nullptr(self.HDR) + else: + # now it gets annoying: finalizer caused a malloc of something + # with a finalizer + last = self.malloced_objects_with_finalizer + while last.next != next: + last = last.next + last.next = lltype.nullptr(self.HDR) + else: + last.next = lltype.nullptr(self.HDR) hdr = next + self.collect_in_progress = False STATISTICS_NUMBERS = 2 Modified: pypy/dist/pypy/rpython/memory/test/test_transformed_gc.py ============================================================================== --- pypy/dist/pypy/rpython/memory/test/test_transformed_gc.py (original) +++ pypy/dist/pypy/rpython/memory/test/test_transformed_gc.py Mon May 22 17:29:06 2006 @@ -347,6 +347,73 @@ res = run([5, 42]) #XXX pure lazyness here too assert res == 12 + def test_finalizer_resurrects(self): + class B(object): + pass + b = B() + b.nextid = 0 + b.num_deleted = 0 + class A(object): + def __init__(self): + self.id = b.nextid + b.nextid += 1 + def __del__(self): + b.num_deleted += 1 + b.a = self + def f(x, y): + a = A() + i = 0 + while i < x: + i += 1 + a = A() + llop.gc__collect(lltype.Void) + llop.gc__collect(lltype.Void) + aid = b.a.id + b.a = None + # check that __del__ is not called again + llop.gc__collect(lltype.Void) + llop.gc__collect(lltype.Void) + return b.num_deleted * 10 + aid + 100 * (b.a is None) + run = self.runner(f, nbargs=2) + res = run([5, 42]) #XXX pure lazyness here too + assert 160 <= res <= 165 + + def test_collect_during_collect(self): + class B(object): + pass + b = B() + b.nextid = 1 + b.num_deleted = 0 + class A(object): + def __init__(self): + self.id = b.nextid + b.nextid += 1 + def __del__(self): + b.num_deleted += 1 + C() + C() + llop.gc__collect(lltype.Void) + class C(A): + def __del__(self): + b.num_deleted += 1 + def f(x, y): + persistent_a1 = A() + persistent_a2 = A() + i = 0 + while i < x: + i += 1 + a = A() + persistent_a3 = A() + persistent_a4 = A() + llop.gc__collect(lltype.Void) + llop.gc__collect(lltype.Void) + b.bla = persistent_a1.id + persistent_a2.id + persistent_a3.id + persistent_a4.id + return b.num_deleted + run = self.runner(f, nbargs=2) + # runs collect recursively 4 times + res = run([4, 42]) #XXX pure lazyness here too + assert res == 12 + def test_cloning(self): B = lltype.GcStruct('B', ('x', lltype.Signed)) A = lltype.GcStruct('A', ('b', lltype.Ptr(B)), From ale at codespeak.net Mon May 22 17:29:18 2006 From: ale at codespeak.net (ale at codespeak.net) Date: Mon, 22 May 2006 17:29:18 +0200 (CEST) Subject: [pypy-svn] r27606 - pypy/dist/pypy/lib/pyontology/test Message-ID: <20060522152918.E7E4710076@code0.codespeak.net> Author: ale Date: Mon May 22 17:29:18 2006 New Revision: 27606 Modified: pypy/dist/pypy/lib/pyontology/test/test_ontology.py Log: Support for OWL:imports Modified: pypy/dist/pypy/lib/pyontology/test/test_ontology.py ============================================================================== --- pypy/dist/pypy/lib/pyontology/test/test_ontology.py (original) +++ pypy/dist/pypy/lib/pyontology/test/test_ontology.py Mon May 22 17:29:18 2006 @@ -582,5 +582,3 @@ O = Ontology() s = URIRef('s') O.imports(s,URIRef('http://www.w3.org/2002/03owlt/imports/support001-A')) - print list(O.graph.triples((None,)*3)) - assert 0 \ No newline at end of file From mwh at codespeak.net Mon May 22 17:33:40 2006 From: mwh at codespeak.net (mwh at codespeak.net) Date: Mon, 22 May 2006 17:33:40 +0200 (CEST) Subject: [pypy-svn] r27607 - in pypy/dist/pypy/rpython/memory: . test Message-ID: <20060522153340.056A210074@code0.codespeak.net> Author: mwh Date: Mon May 22 17:33:39 2006 New Revision: 27607 Modified: pypy/dist/pypy/rpython/memory/gc.py pypy/dist/pypy/rpython/memory/test/test_transformed_gc.py Log: very small tidyings Modified: pypy/dist/pypy/rpython/memory/gc.py ============================================================================== --- pypy/dist/pypy/rpython/memory/gc.py (original) +++ pypy/dist/pypy/rpython/memory/gc.py Mon May 22 17:33:39 2006 @@ -578,9 +578,6 @@ objects.append(pointer.address[0]) # ------------------------------------------------- # begin difference from collect -## llop.debug_pdb(lltype.Void, -## pointer.address[0], target_addr, -## pointer.address[0] == target_addr) if pointer.address[0] == target_addr: pointer.address[0] = source_addr # end difference from collect Modified: pypy/dist/pypy/rpython/memory/test/test_transformed_gc.py ============================================================================== --- pypy/dist/pypy/rpython/memory/test/test_transformed_gc.py (original) +++ pypy/dist/pypy/rpython/memory/test/test_transformed_gc.py Mon May 22 17:33:39 2006 @@ -581,15 +581,14 @@ y = lltype.malloc(S) y.x = 20 z = x - #llop.gc__collect(lltype.Void) llop.gc_x_become(lltype.Void, llmemory.cast_ptr_to_adr(x), llmemory.cast_ptr_to_adr(y)) return z.x run = self.runner(f) res = run([]) - # not implemented yet! - assert res == 20 + assert res == 20 + class TestSemiSpaceGC(TestMarkSweepGC): From ale at codespeak.net Mon May 22 18:27:32 2006 From: ale at codespeak.net (ale at codespeak.net) Date: Mon, 22 May 2006 18:27:32 +0200 (CEST) Subject: [pypy-svn] r27609 - in pypy/dist/pypy/lib/pyontology: . test Message-ID: <20060522162732.5017710071@code0.codespeak.net> Author: ale Date: Mon May 22 18:27:31 2006 New Revision: 27609 Modified: pypy/dist/pypy/lib/pyontology/pyontology.py pypy/dist/pypy/lib/pyontology/test/test_ontology.py Log: Support for complementOf Modified: pypy/dist/pypy/lib/pyontology/pyontology.py ============================================================================== --- pypy/dist/pypy/lib/pyontology/pyontology.py (original) +++ pypy/dist/pypy/lib/pyontology/pyontology.py Mon May 22 18:27:31 2006 @@ -18,6 +18,7 @@ uris[v] = k Class = URIRef(u'http://www.w3.org/2002/07/owl#Class') +Thing_uri = URIRef(u'http://www.w3.org/2002/07/owl#Thing') rdf_type = URIRef(u'http://www.w3.org/1999/02/22-rdf-syntax-ns#type') rdf_rest = URIRef(u'http://www.w3.org/1999/02/22-rdf-syntax-ns#rest') rdf_first = URIRef(u'http://www.w3.org/1999/02/22-rdf-syntax-ns#first') @@ -497,13 +498,23 @@ # add constraint of not var # i.e. the extension of s shall contain all individuals not in var # We need to know all elements and subtract the elements of var -## avar = self.make_var(ClassDomain, var) -## svar = self.make_var(ClassDomain, s) - pass + self.resolve_item(s) + self.resolve_item(var) + avar = self.make_var(ClassDomain, var) + svar = self.make_var(ClassDomain, s) + vals = self.variables[avar].getValues() + x_vals = self.variables[svar].getValues() + for v in x_vals: + if v in vals: + raise ConsistencyFailure("%s cannot have the value %s and be \ + complementOf %s" % (s, v, var)) + for v in self.variables[self.make_var(None,Thing_uri)].getValues(): + if not v in vals: + self.variables[svar].addValue(v) def oneOf(self, s, var): var = self.flatten_rdf_list(var) - print "*******", var, type(var), self.variables[var] +# print "*******", var, type(var), self.variables[var] #avar = self.make_var(List, var) svar = self.make_var(ClassDomain, s) res = self.variables[var].getValues() Modified: pypy/dist/pypy/lib/pyontology/test/test_ontology.py ============================================================================== --- pypy/dist/pypy/lib/pyontology/test/test_ontology.py (original) +++ pypy/dist/pypy/lib/pyontology/test/test_ontology.py Mon May 22 18:27:31 2006 @@ -582,3 +582,29 @@ O = Ontology() s = URIRef('s') O.imports(s,URIRef('http://www.w3.org/2002/03owlt/imports/support001-A')) + +def test_complementof(): + O = Ontology() + a_cls = URIRef('a') + b_cls = URIRef('b') + O.type(a_cls, URIRef(namespaces['owl']+'#Class')) + O.type(b_cls, URIRef(namespaces['owl']+'#Class')) + for i in ['i1', 'i2', 'i3', 'i4']: + O.type(URIRef(i), a_cls) + O.type(URIRef(i), URIRef(namespaces['owl']+'#Thing')) + O.type(URIRef('i5'), URIRef(namespaces['owl']+'#Thing')) + O.complementOf(b_cls, a_cls) + assert O.variables[O.make_var(None, b_cls)].getValues() == ['i5'] + +def test_complementof(): + O = Ontology() + a_cls = URIRef('a') + b_cls = URIRef('b') + O.type(a_cls, URIRef(namespaces['owl']+'#Class')) + O.type(b_cls, URIRef(namespaces['owl']+'#Class')) + for i in ['i1', 'i2', 'i3', 'i4']: + O.type(URIRef(i), a_cls) + O.type(URIRef(i), URIRef(namespaces['owl']+'#Thing')) + O.type(URIRef('i5'), URIRef(namespaces['owl']+'#Thing')) + O.type(URIRef('i4'), b_cls) + raises(ConsistencyFailure, O.complementOf, b_cls, a_cls) From njriley at codespeak.net Mon May 22 18:37:14 2006 From: njriley at codespeak.net (njriley at codespeak.net) Date: Mon, 22 May 2006 18:37:14 +0200 (CEST) Subject: [pypy-svn] r27610 - pypy/branch/njriley-trans/pypy/translator/c/src Message-ID: <20060522163714.B23D510071@code0.codespeak.net> Author: njriley Date: Mon May 22 18:37:13 2006 New Revision: 27610 Modified: pypy/branch/njriley-trans/pypy/translator/c/src/ll_trans.h Log: Much less disgusting hack to dump memory map. Modified: pypy/branch/njriley-trans/pypy/translator/c/src/ll_trans.h ============================================================================== --- pypy/branch/njriley-trans/pypy/translator/c/src/ll_trans.h (original) +++ pypy/branch/njriley-trans/pypy/translator/c/src/ll_trans.h Mon May 22 18:37:13 2006 @@ -85,6 +85,15 @@ int ret_val; ret_val = enable_transactions(); if (ret_val != 0) { + pid_t pid = getpid(); + char *map_path; + asprintf(&map_path, "/proc/%d/maps", pid); + if ( (pid = fork()) == 0) { + execlp("cat", "cat", map_path, NULL); + exit(0); + } + free(map_path); + waitpid(pid, NULL, 0); printf("Load transactional memory module and press return\n"); while (getchar() != '\n'); ret_val = enable_transactions(); From mwh at codespeak.net Mon May 22 18:53:47 2006 From: mwh at codespeak.net (mwh at codespeak.net) Date: Mon, 22 May 2006 18:53:47 +0200 (CEST) Subject: [pypy-svn] r27611 - pypy/dist/pypy/translator/stackless Message-ID: <20060522165347.A727510071@code0.codespeak.net> Author: mwh Date: Mon May 22 18:53:46 2006 New Revision: 27611 Modified: pypy/dist/pypy/translator/stackless/transform.py Log: assert that we don't try to add restart info into the stackless table too late -- as predicted this catches the problems Carl saw in his last checkin earlier. Modified: pypy/dist/pypy/translator/stackless/transform.py ============================================================================== --- pypy/dist/pypy/translator/stackless/transform.py (original) +++ pypy/dist/pypy/translator/stackless/transform.py Mon May 22 18:53:46 2006 @@ -227,6 +227,7 @@ lltype.typeOf(null_state)) self.c_gc_nocollect = model.Constant("gc_nocollect", lltype.Void) + self.is_finished = False # register the prebuilt restartinfos for restartinfo in frame.RestartInfo.prebuilt: self.register_restart_info(restartinfo) @@ -571,6 +572,7 @@ self.register_restart_info(restartinfo) def register_restart_info(self, restartinfo): + assert not self.is_finished rtyper = self.translator.rtyper for frame_info_dict in restartinfo.compress(rtyper): self.masterarray1.append(frame_info_dict) @@ -578,6 +580,7 @@ def finish(self): # compute the final masterarray by copying over the masterarray1, # which is a list of dicts of attributes + self.is_finished = True masterarray = lltype.malloc(frame.FRAME_INFO_ARRAY, len(self.masterarray1), immortal=True) From ericvrp at codespeak.net Tue May 23 10:18:21 2006 From: ericvrp at codespeak.net (ericvrp at codespeak.net) Date: Tue, 23 May 2006 10:18:21 +0200 (CEST) Subject: [pypy-svn] r27613 - pypy/dist/pypy/objspace/std Message-ID: <20060523081821.C746310071@code0.codespeak.net> Author: ericvrp Date: Tue May 23 10:18:21 2006 New Revision: 27613 Modified: pypy/dist/pypy/objspace/std/dicttype.py Log: Attempt to fix broken translation. if..elif was missing an else part so w_clone could possibly be undefined. Modified: pypy/dist/pypy/objspace/std/dicttype.py ============================================================================== --- pypy/dist/pypy/objspace/std/dicttype.py (original) +++ pypy/dist/pypy/objspace/std/dicttype.py Tue May 23 10:18:21 2006 @@ -152,6 +152,8 @@ w_clone = space.allocate_instance(W_DictIter_Values, w_typeobj) elif isinstance(w_self, W_DictIter_Items): w_clone = space.allocate_instance(W_DictIter_Items, w_typeobj) + else: + raise Exception("%s has unknown dictiter type" % w_self) # we cannot call __init__ since we don't have the original dict w_clone.space = space w_clone.content = w_self.content From ale at codespeak.net Tue May 23 11:50:09 2006 From: ale at codespeak.net (ale at codespeak.net) Date: Tue, 23 May 2006 11:50:09 +0200 (CEST) Subject: [pypy-svn] r27617 - pypy/dist/pypy/lib/pyontology Message-ID: <20060523095009.163D41006E@code0.codespeak.net> Author: ale Date: Tue May 23 11:50:08 2006 New Revision: 27617 Modified: pypy/dist/pypy/lib/pyontology/constraint_classes.py pypy/dist/pypy/lib/pyontology/pyontology.py Log: bugfixes and simplifications Modified: pypy/dist/pypy/lib/pyontology/constraint_classes.py ============================================================================== --- pypy/dist/pypy/lib/pyontology/constraint_classes.py (original) +++ pypy/dist/pypy/lib/pyontology/constraint_classes.py Tue May 23 11:50:08 2006 @@ -23,61 +23,17 @@ card = 0 return card -class MaxCardinality(AbstractConstraint): - """Contraint: all values must be distinct""" - - def __init__(self, variable, cardinality): - AbstractConstraint.__init__(self, [variable]) - self.cost = 80 - self.variable = variable - self.cardinality = cardinality +class CardinalityConstraint(AbstractConstraint): - def __repr__(self): - return '<%s %s %i>' % (self.__class__.__name__, str(self._variables[0]), self.cardinality) + def __init__(self, prop, cls_name, var, comp): + AbstractConstraint.__init__(self, [prop]) + self.check_individual = "domains['%s'].getValues() != []" % prop + self.formula = "len(domains['%s'].getValuesPrKey('%s')) %s int(%s)"% (prop, cls_name, comp, var) - def estimateCost(self, domains): - return self.cost - def narrow(self, domains): - """narrowing algorithm for the constraint""" - prop = domains[self.variable].property - props = Linkeddict(domains[prop].getValues()) - dom = domains[self.variable].getValues() - if not dom: - return 0 - cls = dom[0] - card = get_cardinality(props, cls) - if card > self.cardinality: - raise ConsistencyFailure("Maxcardinality of %i exceeded by the value %i" %(self.cardinality,len(props[cls]))) - else: - return 1 - -class MinCardinality(MaxCardinality): - - def narrow(self, domains): - """narrowing algorithm for the constraint""" - prop = domains[self.variable].property - props = Linkeddict(domains[prop].getValues()) - cls = domains[self.variable].getValues()[0] - card = get_cardinality(props, cls) - if card < self.cardinality: - raise ConsistencyFailure("MinCardinality of %i not achieved by the value %i" %(self.cardinality,len(props[cls]))) - else: - return 1 - -class Cardinality(MaxCardinality): - - def narrow(self, domains): - """narrowing algorithm for the constraint""" - prop = domains[self.variable].property - props = Linkeddict(domains[prop].getValues()) - cls = domains[self.variable].getValues()[0] - card = get_cardinality(props, cls) - if card != self.cardinality: - raise ConsistencyFailure("Cardinality of %i exceeded by the value %r for %r" % - (self.cardinality, props[cls], prop)) - else: - return 1 + if eval(self.check_individual): + if not eval(self.formula): + raise ConsistencyFailure class SubClassConstraint(AbstractConstraint): Modified: pypy/dist/pypy/lib/pyontology/pyontology.py ============================================================================== --- pypy/dist/pypy/lib/pyontology/pyontology.py (original) +++ pypy/dist/pypy/lib/pyontology/pyontology.py Tue May 23 11:50:08 2006 @@ -312,7 +312,8 @@ else: avar = self.make_var(Property, p) # Set the values of the property p to o - sub = self.make_var(ClassDomain, s) + self.type(s, Thing_uri) + sub = self.make_var(Thing, s) obj = self.make_var(Thing, o) propdom = self.variables[avar] res = propdom.addValue(sub, obj) @@ -328,8 +329,8 @@ self.consider_triple(triple) def get_individuals_of(self, item): - item_as_subject = self.graph.triples(( None, rdf_type, item)) - for triple in item_as_subject: + item_as_object = self.graph.triples(( None, rdf_type, item)) + for triple in item_as_object: self.consider_triple(triple) def make_var(self, cls=fd, a=''): @@ -562,6 +563,7 @@ def subPropertyOf(self, s, var): # s is a subproperty of var + self.resolve_item(var) avar = self.make_var(Property, var) svar = self.make_var(Property, s) avals = self.variables[avar].getValues() @@ -599,16 +601,12 @@ self.resolve_item(s) svar =self.make_var(Restriction, s) cls = list(self.graph.subjects(None,s))[0] + self.resolve_item(cls) cls_name = self.make_var(ClassDomain, cls) prop = self.variables[svar].property self.variables[svar].TBox[prop] = {'Cardinality': [( '<', int(var))]} - formula = "len(%s[1]) < int(%s)" %(prop, var) - constrain = Expression([prop], formula) - self.constraints.append(constrain) - for cls,vals in self.variables[prop].getValuesPrKey(): - if len(vals) < int(var): - self.variables[svar].addValue(cls) + self.constraints.append(CardinalityConstraint(prop, cls_name, var, '<=')) def minCardinality(self, s, var): """ Len of finite domain of the property shall be greater than or equal to var""" @@ -618,10 +616,8 @@ cls_name = self.make_var(ClassDomain, cls) prop = self.variables[svar].property self.variables[svar].TBox[prop] = {'Cardinality': [( '>', int(var))]} - for cls,vals in self.variables[prop].getValuesPrKey(): - if len(vals) > int(var): - self.variables[svar].addValue(cls) + self.constraints.append(CardinalityConstraint(prop, cls_name, var, '>=')) def cardinality(self, s, var): """ Len of finite domain of the property shall be equal to var""" @@ -631,10 +627,8 @@ cls_name = self.make_var(ClassDomain, cls) prop = self.variables[svar].property self.variables[svar].TBox[prop] = {'Cardinality': [( '=', int(var))]} - for cls,vals in self.variables[prop].getValuesPrKey(): - if len(vals) == int(var): - self.variables[svar].addValue(cls) - + + self.constraints.append(CardinalityConstraint(prop, cls_name, var, '==')) def hasValue(self, s, var): self.resolve_item(s) From ericvrp at codespeak.net Tue May 23 12:20:57 2006 From: ericvrp at codespeak.net (ericvrp at codespeak.net) Date: Tue, 23 May 2006 12:20:57 +0200 (CEST) Subject: [pypy-svn] r27618 - pypy/dist/pypy/objspace/std Message-ID: <20060523102057.EED1B10071@code0.codespeak.net> Author: ericvrp Date: Tue May 23 12:20:56 2006 New Revision: 27618 Modified: pypy/dist/pypy/objspace/std/dicttype.py Log: Should use an OperationError here instead of a regular Exception Modified: pypy/dist/pypy/objspace/std/dicttype.py ============================================================================== --- pypy/dist/pypy/objspace/std/dicttype.py (original) +++ pypy/dist/pypy/objspace/std/dicttype.py Tue May 23 12:20:56 2006 @@ -153,7 +153,8 @@ elif isinstance(w_self, W_DictIter_Items): w_clone = space.allocate_instance(W_DictIter_Items, w_typeobj) else: - raise Exception("%s has unknown dictiter type" % w_self) + msg = "unsupported dictiter type '%s' during pickling" % (w_self, ) + raise OperationError(space.w_TypeError, space.wrap(msg)) # we cannot call __init__ since we don't have the original dict w_clone.space = space w_clone.content = w_self.content From ericvrp at codespeak.net Tue May 23 12:30:48 2006 From: ericvrp at codespeak.net (ericvrp at codespeak.net) Date: Tue, 23 May 2006 12:30:48 +0200 (CEST) Subject: [pypy-svn] r27619 - pypy/dist/pypy/translator/goal Message-ID: <20060523103048.7C7C810071@code0.codespeak.net> Author: ericvrp Date: Tue May 23 12:30:47 2006 New Revision: 27619 Modified: pypy/dist/pypy/translator/goal/bench-cronjob.py Log: Create a profile based optimized executable from the llvm c backend generated file. The exe this produces is twice as fast as the one generated with the llvm x86 backend. This version uses genc's exception transformer + the raisingop2direct_call transformer + some hackish code that uses a ringbuffer instead of garbage collected malloced data for short lived exception. It produces the fastest pypy so far (some 3.3x slower that CPython). Modified: pypy/dist/pypy/translator/goal/bench-cronjob.py ============================================================================== --- pypy/dist/pypy/translator/goal/bench-cronjob.py (original) +++ pypy/dist/pypy/translator/goal/bench-cronjob.py Tue May 23 12:30:47 2006 @@ -7,84 +7,78 @@ homedir = os.getenv('HOME') tmpdir = py.std.tempfile.gettempdir() + '/usession-' + os.environ['USER'] + '/' +cflags = "-march=pentium4 -O3 -fomit-frame-pointer" +lflags = "-lgc -lm -lpthread" + +def run(cmd): + print 'RUN:', cmd + os.system(cmd) def update_pypy(): os.chdir(homedir + '/projects/pypy-dist') - os.system('svn up 2>&1') + run('svn up 2>&1') def update_llvm(): os.chdir(homedir + '/projects/llvm') - os.system('cvs -q up 2>&1') - os.system('make -k -j3 tools-only 2>&1') + run('cvs -q up 2>&1') + run('make -k -j3 tools-only 2>&1') def compile_llvm_variants(revision): ll2bc(revision) + + bc2c_exe(revision, 'from richards import *;main(iterations=1)') + bc2x86_exe(revision, 'x86A', '-enable-x86-fastcc -relocation-model=static -join-liveintervals') bc2x86_exe(revision, 'x86B', '-relocation-model=static') bc2x86_exe(revision, 'x86C', '') - bc2c_exe(revision) def ll2bc(revision): cmd = 'cp %spypy.ll pypy/translator/goal/archive/pypy-%s.ll' % (tmpdir, revision) - print cmd - os.system(cmd) + run(cmd) opts = optimizations(simple=False, use_gcc=False) cmd = '~/bin/llvm-as < %spypy.ll | ~/bin/opt %s -f -o %spypy.bc' % ( tmpdir, opts, tmpdir) - print cmd - os.system(cmd) + run(cmd) cmd = 'cp %spypy.bc pypy/translator/goal/archive/pypy-%s.bc' % (tmpdir, revision) - print cmd - os.system(cmd) - - -def bc2c_exe(revision): - b = "%spypy-llvm-%s-c" % (tmpdir, revision) - cmd = "~/bin/llc %spypy.bc -march=c -f -o %s.c" % (tmpdir, b) - print cmd - os.system(cmd) - - cmd = "cp %s.c pypy/translator/goal/archive" % b - print cmd - os.system(cmd) + run(cmd) - cmd = "gcc %s.c -S -O3 -fomit-frame-pointer -o %s.s" % (b, b) - print cmd - os.system(cmd) - - cmd = "cp %s.s pypy/translator/goal/archive" % b - print cmd - os.system(cmd) - - cmd = "gcc %s.s -lgc -lm -lpthread -pipe -o %s" % (b, b) #XXX -static - print cmd - os.system(cmd) - - cmd = "cp %s pypy/translator/goal" % b - print cmd - os.system(cmd) +def bc2c_exe(revision, profile_command=None): + filename = "pypy-llvm-%s-c" % revision + b = tmpdir + filename + + run("~/bin/llc %spypy.bc -march=c -f -o %s.c" % (tmpdir, b)) + run("cp %s.c pypy/translator/goal/archive" % b) + run("gcc %s.c %s -S -o %s.s" % (b, cflags, b)) + run("cp %s.s pypy/translator/goal/archive" % b) + run("gcc %s.s %s -o %s" % (b, lflags, b)) + run("cp %s pypy/translator/goal" % b) + + if profile_command: + run("gcc %s.c -fprofile-generate %s -S -o %s.s" % (b, cflags, b)) + run("gcc %s.s -fprofile-generate %s -o %s" % (b, lflags, b)) + run("%s -c '%s'" % (b, profile_command)) + run("gcc %s.c -fprofile-use %s -S -o %s.s" % (b, cflags, b)) + run("cp %s.s pypy/translator/goal/archive/%s-prof.s" % (b, filename)) + run("gcc %s.s -fprofile-use %s -o %s" % (b, lflags, b)) + run("cp %s pypy/translator/goal/%s-prof" % (b, filename)) def bc2x86_exe(revision, name_extra, llc_extra_options): b = "%spypy-llvm-%s-%s" % (tmpdir, revision, name_extra) cmd = "~/bin/llc %spypy.bc %s -f -o %s.s" % (tmpdir, llc_extra_options, b) - print cmd - os.system(cmd) + run(cmd) cmd = 'cp %s.s pypy/translator/goal/archive' % b - print cmd - os.system(cmd) + run(cmd) - cmd = "gcc %s.s -lgc -lm -lpthread -pipe -o %s" % (b, b) #XXX -static - print cmd - os.system(cmd) + cmd = "gcc %s.s %s -o %s" % (b, lflags, b) + run(cmd) cmd = "cp %s pypy/translator/goal" % b - print cmd - os.system(cmd) + run(cmd) def compile(backend): @@ -98,13 +92,13 @@ targetoptions = '' if backend == 'llvm': - translateoptions = ' --source' + translateoptions = ' --source --raisingop2direct_call' else: translateoptions = '' os.chdir(homedir + '/projects/pypy-dist/pypy/translator/goal') - os.system('/usr/local/bin/python translate.py --backend=%(backend)s%(featureoptions)s%(translateoptions)s --text --batch targetpypystandalone.py %(targetoptions)s 2>&1' % locals()) - os.system('mv %s/entry_point.ll %s/pypy.ll' % (tmpdir, tmpdir)) + run('/usr/local/bin/python translate.py --backend=%(backend)s%(featureoptions)s%(translateoptions)s --text --batch targetpypystandalone.py %(targetoptions)s 2>&1' % locals()) + run('mv %s/entry_point.ll %s/pypy.ll' % (tmpdir, tmpdir)) os.chdir(homedir + '/projects/pypy-dist') try: @@ -126,14 +120,14 @@ os.unlink(basename) def benchmark(): - #os.system('cat /proc/cpuinfo') - #os.system('free') + #run('cat /proc/cpuinfo') + #run('free') os.chdir(homedir + '/projects/pypy-dist/pypy/translator/goal') - os.system('/usr/local/bin/python bench-unix.py 2>&1 | tee benchmark.txt' % locals()) - os.system('echo "
"    >  benchmark.html')
-    os.system('cat benchmark.txt           >> benchmark.html')
-    os.system('echo "
" >> benchmark.html') - os.system('scp benchmark.html ericvrp at codespeak.net:public_html/benchmark/index.html') + run('/usr/local/bin/python bench-unix.py 2>&1 | tee benchmark.txt' % locals()) + run('echo "
"    >  benchmark.html')
+    run('cat benchmark.txt           >> benchmark.html')
+    run('echo "
" >> benchmark.html') + run('scp benchmark.html ericvrp at codespeak.net:public_html/benchmark/index.html') def main(backends=[]): if backends == []: #_ prefix means target specific option From antocuni at codespeak.net Tue May 23 14:30:42 2006 From: antocuni at codespeak.net (antocuni at codespeak.net) Date: Tue, 23 May 2006 14:30:42 +0200 (CEST) Subject: [pypy-svn] r27620 - in pypy/dist/pypy: annotation rpython rpython/lltypesystem rpython/ootypesystem rpython/ootypesystem/test rpython/test Message-ID: <20060523123042.8BCCA10068@code0.codespeak.net> Author: antocuni Date: Tue May 23 14:30:22 2006 New Revision: 27620 Modified: pypy/dist/pypy/annotation/builtin.py pypy/dist/pypy/rpython/lltypesystem/ll_str.py pypy/dist/pypy/rpython/lltypesystem/rstr.py pypy/dist/pypy/rpython/ootypesystem/ll_str.py pypy/dist/pypy/rpython/ootypesystem/ooregistry.py pypy/dist/pypy/rpython/ootypesystem/ootype.py pypy/dist/pypy/rpython/ootypesystem/rbuiltin.py pypy/dist/pypy/rpython/ootypesystem/test/test_ooann.py pypy/dist/pypy/rpython/ootypesystem/test/test_ooregistry.py pypy/dist/pypy/rpython/ootypesystem/test/test_oortype.py pypy/dist/pypy/rpython/rfloat.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_rstr.py Log: - Added support for float to string conversion to ootypesystem. - Removed the temporary oostring2 which was used for playing with ooregistry. - Moved oostring and ooparse_int implementatio to ooregistry.py. Due to the use of extregistry now tests should import ootypesystem.ooregistry so that entries are registered. Modified: pypy/dist/pypy/annotation/builtin.py ============================================================================== --- pypy/dist/pypy/annotation/builtin.py (original) +++ pypy/dist/pypy/annotation/builtin.py Tue May 23 14:30:22 2006 @@ -521,16 +521,6 @@ assert isinstance(i, SomeOOInstance) return SomeInteger() -def oostring(obj, base): - assert isinstance(obj, (SomeInteger, SomeChar, SomeOOInstance)) - assert isinstance(base, SomeInteger) - return SomeOOInstance(ootype.String) - -def ooparse_int(s, base): - assert isinstance(s, SomeOOInstance) and s.ootype is ootype.String - assert isinstance(base, SomeInteger) - return SomeInteger() - BUILTIN_ANALYZERS[ootype.instanceof] = instanceof BUILTIN_ANALYZERS[ootype.new] = new BUILTIN_ANALYZERS[ootype.null] = null @@ -538,8 +528,6 @@ BUILTIN_ANALYZERS[ootype.classof] = classof BUILTIN_ANALYZERS[ootype.subclassof] = subclassof BUILTIN_ANALYZERS[ootype.ooidentityhash] = ooidentityhash -BUILTIN_ANALYZERS[ootype.oostring] = oostring -BUILTIN_ANALYZERS[ootype.ooparse_int] = ooparse_int #________________________________ # non-gc objects Modified: pypy/dist/pypy/rpython/lltypesystem/ll_str.py ============================================================================== --- pypy/dist/pypy/rpython/lltypesystem/ll_str.py (original) +++ pypy/dist/pypy/rpython/lltypesystem/ll_str.py Tue May 23 14:30:22 2006 @@ -105,3 +105,9 @@ result.chars[j] = temp[len-j-1] j += 1 return result + +def ll_float_str(repr, f): + from pypy.rpython.module.ll_strtod import ll_strtod_formatd + from pypy.rpython.lltypesystem.rstr import percent_f + return ll_strtod_formatd(percent_f, f) + Modified: pypy/dist/pypy/rpython/lltypesystem/rstr.py ============================================================================== --- pypy/dist/pypy/rpython/lltypesystem/rstr.py (original) +++ pypy/dist/pypy/rpython/lltypesystem/rstr.py Tue May 23 14:30:22 2006 @@ -702,3 +702,5 @@ list_str_open_bracket = string_repr.convert_const("[") list_str_close_bracket = string_repr.convert_const("]") list_str_sep = string_repr.convert_const(", ") + +percent_f = string_repr.convert_const("%f") Modified: pypy/dist/pypy/rpython/ootypesystem/ll_str.py ============================================================================== --- pypy/dist/pypy/rpython/ootypesystem/ll_str.py (original) +++ pypy/dist/pypy/rpython/ootypesystem/ll_str.py Tue May 23 14:30:22 2006 @@ -36,4 +36,5 @@ buf.ll_append(oostring(i, const(8))) return buf.ll_build() - +def ll_float_str(repr, f): + return oostring(f, const(-1)) Modified: pypy/dist/pypy/rpython/ootypesystem/ooregistry.py ============================================================================== --- pypy/dist/pypy/rpython/ootypesystem/ooregistry.py (original) +++ pypy/dist/pypy/rpython/ootypesystem/ooregistry.py Tue May 23 14:30:22 2006 @@ -2,13 +2,14 @@ from pypy.annotation import model as annmodel from pypy.rpython.ootypesystem import ootype -class OOStringEntry(ExtRegistryEntry): - _about_ = ootype.oostring2 +class Entry_oostring(ExtRegistryEntry): + _about_ = ootype.oostring def compute_result_annotation(self, obj_s, base_s): assert isinstance(obj_s, (annmodel.SomeInteger, - annmodel.SomeChar, - annmodel.SomeOOInstance)) + annmodel.SomeChar, + annmodel.SomeFloat, + annmodel.SomeOOInstance)) assert isinstance(base_s, annmodel.SomeInteger) return annmodel.SomeOOInstance(ootype.String) @@ -16,7 +17,25 @@ assert isinstance(hop.args_s[0],(annmodel.SomeInteger, annmodel.SomeChar, annmodel.SomeString, + annmodel.SomeFloat, annmodel.SomeOOInstance)) assert isinstance(hop.args_s[1], annmodel.SomeInteger) return hop.genop('oostring', hop.args_v, resulttype = ootype.String) - + + +class Entry_ooparse_int(ExtRegistryEntry): + _about_ = ootype.ooparse_int + + def compute_result_annotation(self, str_s, base_s): + assert isinstance(str_s, annmodel.SomeOOInstance)\ + and str_s.ootype is ootype.String + assert isinstance(base_s, annmodel.SomeInteger) + return annmodel.SomeInteger() + + def specialize_call(self, hop): + assert isinstance(hop.args_s[0], annmodel.SomeOOInstance)\ + and hop.args_s[0].ootype is ootype.String + assert isinstance(hop.args_s[1], annmodel.SomeInteger) + hop.has_implicit_exception(ValueError) + hop.exception_is_here() + return hop.genop('ooparse_int', hop.args_v, resulttype = ootype.Signed) Modified: pypy/dist/pypy/rpython/ootypesystem/ootype.py ============================================================================== --- pypy/dist/pypy/rpython/ootypesystem/ootype.py (original) +++ pypy/dist/pypy/rpython/ootypesystem/ootype.py Tue May 23 14:30:22 2006 @@ -1175,18 +1175,6 @@ obj = '<%s object>' % obj._inst._TYPE._name return make_string(str(obj)) -def oostring2(obj, base): - """ - Temp function for playing with extregistry. - """ - if isinstance(obj, int): - assert base in (-1, 8, 10, 16) - fmt = {-1:'%d', 8:'%o', 10:'%d', 16:'%x'}[base] - obj = fmt % obj - elif isinstance(obj, _view): - obj = '<%s object>' % obj._inst._TYPE._name - return make_string(str(obj)) - def ooparse_int(s, base): return int(s._str, base) Modified: pypy/dist/pypy/rpython/ootypesystem/rbuiltin.py ============================================================================== --- pypy/dist/pypy/rpython/ootypesystem/rbuiltin.py (original) +++ pypy/dist/pypy/rpython/ootypesystem/rbuiltin.py Tue May 23 14:30:22 2006 @@ -57,22 +57,6 @@ else: raise TyperError("XXX missing impl of isinstance(x, variable)") -def rtype_oostring(hop): - assert isinstance(hop.args_s[0],(annmodel.SomeInteger, - annmodel.SomeChar, - annmodel.SomeString, - annmodel.SomeOOInstance)) - assert isinstance(hop.args_s[1], annmodel.SomeInteger) - return hop.genop('oostring', hop.args_v, resulttype = ootype.String) - -def rtype_ooparse_int(hop): - assert isinstance(hop.args_s[0], annmodel.SomeOOInstance)\ - and hop.args_s[0].ootype is ootype.String - assert isinstance(hop.args_s[1], annmodel.SomeInteger) - hop.has_implicit_exception(ValueError) - hop.exception_is_here() - return hop.genop('ooparse_int', hop.args_v, resulttype = ootype.Signed) - BUILTIN_TYPER = {} BUILTIN_TYPER[ootype.new] = rtype_new BUILTIN_TYPER[ootype.null] = rtype_null @@ -81,5 +65,3 @@ BUILTIN_TYPER[ootype.runtimenew] = rtype_runtimenew BUILTIN_TYPER[ootype.ooidentityhash] = rtype_ooidentityhash BUILTIN_TYPER[isinstance] = rtype_builtin_isinstance -BUILTIN_TYPER[ootype.oostring] = rtype_oostring -BUILTIN_TYPER[ootype.ooparse_int] = rtype_ooparse_int Modified: pypy/dist/pypy/rpython/ootypesystem/test/test_ooann.py ============================================================================== --- pypy/dist/pypy/rpython/ootypesystem/test/test_ooann.py (original) +++ pypy/dist/pypy/rpython/ootypesystem/test/test_ooann.py Tue May 23 14:30:22 2006 @@ -3,6 +3,7 @@ from pypy.objspace.flow import FlowObjSpace from pypy.annotation.annrpython import RPythonAnnotator import exceptions +from pypy.rpython.ootypesystem import ooregistry # side effects def test_simple_new(): Modified: pypy/dist/pypy/rpython/ootypesystem/test/test_ooregistry.py ============================================================================== --- pypy/dist/pypy/rpython/ootypesystem/test/test_ooregistry.py (original) +++ pypy/dist/pypy/rpython/ootypesystem/test/test_ooregistry.py Tue May 23 14:30:22 2006 @@ -4,28 +4,28 @@ from pypy.rpython.ootypesystem import ootype from pypy.rpython.test.test_llinterp import interpret -def test_oostring2_annotation(): +def test_oostring_annotation(): def oof(): - return ootype.oostring2 + return ootype.oostring a = RPythonAnnotator() s = a.build_types(oof, []) assert isinstance(s, annmodel.SomeBuiltin) -def test_oostring2_result_annotation(): +def test_oostring_result_annotation(): def oof(): - return ootype.oostring2(42, -1) + return ootype.oostring(42, -1) a = RPythonAnnotator() s = a.build_types(oof, []) assert isinstance(s, annmodel.SomeOOInstance) and s.ootype is ootype.String -def test_oostring2_call(): +def test_oostring_call(): def const(c): return c - + def oof(ch): - return ootype.oostring2(ch, const(-1)) + return ootype.oostring(ch, const(-1)) ch = 'a' res = interpret(oof, [ch], type_system='ootype') Modified: pypy/dist/pypy/rpython/ootypesystem/test/test_oortype.py ============================================================================== --- pypy/dist/pypy/rpython/ootypesystem/test/test_oortype.py (original) +++ pypy/dist/pypy/rpython/ootypesystem/test/test_oortype.py Tue May 23 14:30:22 2006 @@ -7,6 +7,7 @@ from pypy.objspace.flow import FlowObjSpace from pypy.translator.translator import TranslationContext, graphof from pypy.rpython.test.test_llinterp import interpret +from pypy.rpython.ootypesystem import ooregistry # side effects def gengraph(f, args=[], viewBefore=False, viewAfter=False): t = TranslationContext() Modified: pypy/dist/pypy/rpython/rfloat.py ============================================================================== --- pypy/dist/pypy/rpython/rfloat.py (original) +++ pypy/dist/pypy/rpython/rfloat.py Tue May 23 14:30:22 2006 @@ -136,13 +136,12 @@ rtype_float = rtype_pos + # version picked by specialisation based on which + # type system rtyping is using, from .ll_str module def ll_str(self, f): - from pypy.rpython.module.ll_strtod import ll_strtod_formatd - return ll_strtod_formatd(percent_f, f) + pass + ll_str._annspecialcase_ = "specialize:ts('ll_str.ll_float_str')" -# XXX this will need to be type system independent -from pypy.rpython.lltypesystem.rstr import string_repr -percent_f = string_repr.convert_const("%f") TAKE_NEXT = float(2**31) 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 Tue May 23 14:30:22 2006 @@ -1,7 +1,8 @@ from pypy.translator.translator import TranslationContext from pypy.rpython.test import snippet from pypy.rpython.test.test_llinterp import interpret - +from pypy.rpython.test.tool import BaseRtypingTest, LLRtypeMixin, OORtypeMixin +from pypy.rpython.ootypesystem import ooregistry # side effects class TestSnippet(object): @@ -43,15 +44,23 @@ res = interpret(fn, [2.34]) assert res == fn(2.34) -def test_float2str(): - def fn(f): - return str(f) - - res = interpret(fn, [1.5]) - assert float(''.join(res.chars)) == 1.5 - def test_hash(): def fn(f): return hash(f) res = interpret(fn, [1.5]) assert res == hash(1.5) + +class BaseTestRfloat(BaseRtypingTest): + + def test_float2str(self): + def fn(f): + return str(f) + + res = self.interpret(fn, [1.5]) + assert float(self.ll_to_string(res)) == 1.5 + +class TestLLtype(BaseTestRfloat, LLRtypeMixin): + pass + +class TestOOtype(BaseTestRfloat, OORtypeMixin): + pass 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 Tue May 23 14:30:22 2006 @@ -5,6 +5,7 @@ from pypy.rpython.test.test_llinterp import interpret from pypy.rpython.rarithmetic import r_uint, r_longlong, r_ulonglong from pypy.rpython.test.tool import BaseRtypingTest, LLRtypeMixin, OORtypeMixin +from pypy.rpython.ootypesystem import ooregistry # side effects class TestSnippet(object): 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 Tue May 23 14:30:22 2006 @@ -13,6 +13,7 @@ from pypy.translator.translator import TranslationContext from pypy.objspace.flow.model import Constant, Variable from pypy.rpython.test.tool import BaseRtypingTest, LLRtypeMixin, OORtypeMixin +from pypy.rpython.ootypesystem import ooregistry # side effects # undo the specialization parameter for n1 in 'get set del'.split(): 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 May 23 14:30:22 2006 @@ -5,6 +5,7 @@ from pypy.rpython.rtyper import RPythonTyper, TyperError from pypy.rpython.test.tool import BaseRtypingTest, LLRtypeMixin, OORtypeMixin from pypy.rpython.llinterp import LLException +from pypy.rpython.ootypesystem import ooregistry # side effects def test_parse_fmt(): parse = AbstractLLHelpers.parse_fmt_string From antocuni at codespeak.net Tue May 23 16:00:05 2006 From: antocuni at codespeak.net (antocuni at codespeak.net) Date: Tue, 23 May 2006 16:00:05 +0200 (CEST) Subject: [pypy-svn] r27621 - in pypy/dist/pypy: annotation rpython/test Message-ID: <20060523140005.4DB9310068@code0.codespeak.net> Author: antocuni Date: Tue May 23 15:59:54 2006 New Revision: 27621 Modified: pypy/dist/pypy/annotation/annrpython.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_rstr.py Log: ooregistry is automatically imported by RPythonAnnotator.__init__, so it is no longer necessary to explicitly import it. Modified: pypy/dist/pypy/annotation/annrpython.py ============================================================================== --- pypy/dist/pypy/annotation/annrpython.py (original) +++ pypy/dist/pypy/annotation/annrpython.py Tue May 23 15:59:54 2006 @@ -22,6 +22,8 @@ See description in doc/translation.txt.""" def __init__(self, translator=None, policy=None, bookkeeper=None): + import pypy.rpython.ootypesystem.ooregistry # has side effects + if translator is None: # interface for tests from pypy.translator.translator import TranslationContext 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 Tue May 23 15:59:54 2006 @@ -2,7 +2,6 @@ from pypy.rpython.test import snippet from pypy.rpython.test.test_llinterp import interpret from pypy.rpython.test.tool import BaseRtypingTest, LLRtypeMixin, OORtypeMixin -from pypy.rpython.ootypesystem import ooregistry # side effects class TestSnippet(object): 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 Tue May 23 15:59:54 2006 @@ -5,7 +5,6 @@ from pypy.rpython.test.test_llinterp import interpret from pypy.rpython.rarithmetic import r_uint, r_longlong, r_ulonglong from pypy.rpython.test.tool import BaseRtypingTest, LLRtypeMixin, OORtypeMixin -from pypy.rpython.ootypesystem import ooregistry # side effects class TestSnippet(object): 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 Tue May 23 15:59:54 2006 @@ -13,7 +13,6 @@ from pypy.translator.translator import TranslationContext from pypy.objspace.flow.model import Constant, Variable from pypy.rpython.test.tool import BaseRtypingTest, LLRtypeMixin, OORtypeMixin -from pypy.rpython.ootypesystem import ooregistry # side effects # undo the specialization parameter for n1 in 'get set del'.split(): 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 May 23 15:59:54 2006 @@ -5,7 +5,6 @@ from pypy.rpython.rtyper import RPythonTyper, TyperError from pypy.rpython.test.tool import BaseRtypingTest, LLRtypeMixin, OORtypeMixin from pypy.rpython.llinterp import LLException -from pypy.rpython.ootypesystem import ooregistry # side effects def test_parse_fmt(): parse = AbstractLLHelpers.parse_fmt_string From arigo at codespeak.net Tue May 23 16:41:22 2006 From: arigo at codespeak.net (arigo at codespeak.net) Date: Tue, 23 May 2006 16:41:22 +0200 (CEST) Subject: [pypy-svn] r27622 - in pypy/dist/pypy: rpython rpython/lltypesystem rpython/memory rpython/memory/test translator/c Message-ID: <20060523144122.11A6C10061@code0.codespeak.net> Author: arigo Date: Tue May 23 16:41:19 2006 New Revision: 27622 Modified: pypy/dist/pypy/rpython/annlowlevel.py pypy/dist/pypy/rpython/lltypesystem/lltype.py pypy/dist/pypy/rpython/memory/gc.py pypy/dist/pypy/rpython/memory/gctransform.py pypy/dist/pypy/rpython/memory/test/test_transformed_gc.py pypy/dist/pypy/translator/c/database.py pypy/dist/pypy/translator/c/funcgen.py pypy/dist/pypy/translator/c/gc.py pypy/dist/pypy/translator/c/node.py Log: Trying to sort out the dependencies in order between the stackless and the gc transforms. The isgchelper flag was getting in the way because gc helpers must almost all be stackless transformed too (e.g. to allow UnwindException to pass through a call to a destructor). Some obscure hacks now allow cooperation between the mixlevelannotator and the genc database about delayed functions. It is now ok to get() delayed function pointers. It forces the unique pypy_g_* name of the function to be computed, but the FuncNode is not built. Instead, the complete() method periodically checks if these delayed pointers have been resolved (e.g. by a finish()). The finish() of the gc transformer is now in two parts: finish_helpers() finishes the mixlevelannotator; then finish_tables() computes the final GC tables. Documented in complete() the precise order in which these finish() are called and why. Modified: pypy/dist/pypy/rpython/annlowlevel.py ============================================================================== --- pypy/dist/pypy/rpython/annlowlevel.py (original) +++ pypy/dist/pypy/rpython/annlowlevel.py Tue May 23 16:41:19 2006 @@ -161,7 +161,11 @@ def graph2delayed(self, graph): FUNCTYPE = lltype.ForwardReference() - delayedptr = lltype._ptr(lltype.Ptr(FUNCTYPE), "delayed!", solid=True) + # obscure hack: embed the name of the function in the string, so + # that the genc database can get it even before the delayedptr + # is really computed + name = "delayed!%s" % (graph.name,) + delayedptr = lltype._ptr(lltype.Ptr(FUNCTYPE), name, solid=True) self.delayedfuncs.append((delayedptr, graph)) return delayedptr Modified: pypy/dist/pypy/rpython/lltypesystem/lltype.py ============================================================================== --- pypy/dist/pypy/rpython/lltypesystem/lltype.py (original) +++ pypy/dist/pypy/rpython/lltypesystem/lltype.py Tue May 23 16:41:19 2006 @@ -790,6 +790,8 @@ p = _ptr(Ptr(typeOf(container)), container, p._solid) return p +class DelayedPointer(Exception): + pass class _ptr(object): __slots__ = ('_TYPE', '_T', @@ -843,7 +845,10 @@ raise TypeError("pointer objects are not hashable") def __nonzero__(self): - return self._obj is not None + try: + return self._obj is not None + except DelayedPointer: + return True # assume it's not a delayed null # _setobj, _getobj and _obj0 are really _internal_ implementations details of _ptr, # use _obj if necessary instead ! @@ -866,8 +871,10 @@ if obj is None: raise RuntimeError("accessing already garbage collected %r" % (self._T,)) - if not isinstance(obj, int): + if isinstance(obj, _container): obj._check() + elif isinstance(obj, str) and obj.startswith("delayed!"): + raise DelayedPointer return obj _obj = property(_getobj) @@ -968,6 +975,8 @@ return '* %s' % (self._obj, ) except RuntimeError: return '* DEAD %s' % self._T + except DelayedPointer: + return '* %s' % (self._obj0,) def __call__(self, *args): if isinstance(self._T, FuncType): Modified: pypy/dist/pypy/rpython/memory/gc.py ============================================================================== --- pypy/dist/pypy/rpython/memory/gc.py (original) +++ pypy/dist/pypy/rpython/memory/gc.py Tue May 23 16:41:19 2006 @@ -218,10 +218,6 @@ # call __del__, move the object to the list of object-without-del import time from pypy.rpython.lltypesystem.lloperation import llop - # XXX the following two lines should not be there, but without them - # there is a strange crash in decodestate when using stackless :-( - if self.collect_in_progress: - return if DEBUG_PRINT: llop.debug_print(lltype.Void, 'collecting...') start_time = time.time() @@ -383,6 +379,8 @@ #llop.debug_view(lltype.Void, self.malloced_objects, self.malloced_objects_with_finalizer, size_gc_header) finalizer(obj) if not self.collect_in_progress: # another collection was caused? + llop.debug_print(lltype.Void, "outer collect interrupted " + "by recursive collect") return if not last: if self.malloced_objects_with_finalizer == next: Modified: pypy/dist/pypy/rpython/memory/gctransform.py ============================================================================== --- pypy/dist/pypy/rpython/memory/gctransform.py (original) +++ pypy/dist/pypy/rpython/memory/gctransform.py Tue May 23 16:41:19 2006 @@ -32,7 +32,7 @@ class GCTransformer(object): - finished = False + finished_helpers = False def __init__(self, translator, inline=False): self.translator = translator @@ -265,28 +265,32 @@ return [SpaceOperation("direct_call", op.args, op.result)] def annotate_helper(self, ll_helper, ll_args, ll_result): - assert not self.finished + assert not self.finished_helpers args_s = map(annmodel.lltype_to_annotation, ll_args) s_result = annmodel.lltype_to_annotation(ll_result) - g = self.mixlevelannotator.getgraph(ll_helper, args_s, s_result) - FUNC = lltype.FuncType(ll_args, ll_result) - ptr = rmodel.inputconst( - lltype.Ptr(FUNC), - lltype.functionptr(FUNC, g.name, graph=g, isgchelper=True)) - return g, ptr.value + graph = self.mixlevelannotator.getgraph(ll_helper, args_s, s_result) + # the produced graphs does not need to be fully transformed + self.need_minimal_transform(graph) + return self.mixlevelannotator.graph2delayed(graph) def inittime_helper(self, ll_helper, ll_args, ll_result): - graph, ptr = self.annotate_helper(ll_helper, ll_args, ll_result) - self.need_minimal_transform(graph) - return Constant(ptr, lltype.Ptr(lltype.FuncType(ll_args, ll_result))) + ptr = self.annotate_helper(ll_helper, ll_args, ll_result) + return Constant(ptr, lltype.typeOf(ptr)) - def finish(self): + def finish_helpers(self): if self.translator is not None: self.mixlevelannotator.finish_annotate() - self.finished = True + self.finished_helpers = True if self.translator is not None: self.mixlevelannotator.finish_rtype() + def finish_tables(self): + pass + + def finish(self): + self.finish_helpers() + self.finish_tables() + class MinimalGCTransformer(GCTransformer): def __init__(self, parenttransformer): GCTransformer.__init__(self, parenttransformer.translator) @@ -450,7 +454,7 @@ dealloc_fptr = self.dynamic_deallocation_funcptr_for_type(PTRTYPE.TO) cdealloc_fptr = rmodel.inputconst( - lltype.Ptr(ADDRESS_VOID_FUNC), dealloc_fptr) + lltype.typeOf(dealloc_fptr), dealloc_fptr) result.append(SpaceOperation("direct_call", [self.decref_ptr, adr1, cdealloc_fptr], @@ -493,9 +497,6 @@ result.extend(self.pop_alive(oldval)) return result - def finish(self): - super(RefcountingGCTransformer, self).finish() - ## -- maybe add this for tests and for consistency -- ## def consider_constant(self, TYPE, value): ## p = value._as_ptr() @@ -565,9 +566,7 @@ 'll_call_destructor': ll_call_destructor} exec src in d this = d['ll_deallocator'] - g, fptr = self.annotate_helper(this, [llmemory.Address], lltype.Void) - # the produced deallocator graph does not need to be transformed - self.need_minimal_transform(g) + fptr = self.annotate_helper(this, [llmemory.Address], lltype.Void) self.static_deallocator_funcptrs[TYPE] = fptr for p in find_gc_ptrs_in_type(TYPE): self.static_deallocation_funcptr_for_type(p.TO) @@ -599,9 +598,7 @@ rtti = queryptr(v) gcheader.signed[0] = 0 llop.gc_call_rtti_destructor(lltype.Void, rtti, addr) - g, fptr = self.annotate_helper(ll_dealloc, [llmemory.Address], lltype.Void) - self.need_minimal_transform(g) - + fptr = self.annotate_helper(ll_dealloc, [llmemory.Address], lltype.Void) self.dynamic_deallocator_funcptrs[TYPE] = fptr self.queryptr2dynamic_deallocator_funcptr[queryptr._obj] = fptr return fptr @@ -663,9 +660,6 @@ """ for boehm it is enough to do nothing""" return [SpaceOperation("same_as", [Constant(None, lltype.Void)], op.result)] - def finish(self): - super(BoehmGCTransformer, self).finish() - def finalizer_funcptr_for_type(self, TYPE): if TYPE in self.finalizer_funcptrs: return self.finalizer_funcptrs[TYPE] @@ -690,7 +684,7 @@ " v = cast_adr_to_ptr(addr, PTR_TYPE)\n" "%s\n")%(static_body,) exec src in d - g, fptr = self.annotate_helper(d['ll_finalizer'], [llmemory.Address], lltype.Void) + fptr = self.annotate_helper(d['ll_finalizer'], [llmemory.Address], lltype.Void) elif destrptr: EXC_INSTANCE_TYPE = self.translator.rtyper.exceptiondata.lltype_of_exception_value def ll_finalizer(addr): @@ -698,12 +692,10 @@ v = llmemory.cast_adr_to_ptr(addr, DESTR_ARG) ll_call_destructor(destrptr, v) llop.gc_restore_exception(lltype.Void, exc_instance) - g, fptr = self.annotate_helper(ll_finalizer, [llmemory.Address], lltype.Void) + fptr = self.annotate_helper(ll_finalizer, [llmemory.Address], lltype.Void) else: - g = fptr = None + fptr = None - if g: - self.need_minimal_transform(g) self.finalizer_funcptrs[TYPE] = fptr return fptr @@ -735,6 +727,7 @@ class FrameworkGCTransformer(GCTransformer): use_stackless = False extra_static_slots = 0 + finished_tables = False from pypy.rpython.memory.gc import MarkSweepGC as GCClass GC_PARAMS = {'start_heap_size': 8*1024*1024 # XXX adjust @@ -975,7 +968,7 @@ try: return self.id_of_type[TYPE] except KeyError: - assert not self.finished + assert not self.finished_tables assert isinstance(TYPE, (lltype.GcStruct, lltype.GcArray)) # Record the new type_id description as a small dict for now. # It will be turned into a Struct("type_info") in finish() @@ -1037,11 +1030,10 @@ def ll_finalizer(addr): v = llmemory.cast_adr_to_ptr(addr, DESTR_ARG) ll_call_destructor(destrptr, v) - g, fptr = self.annotate_helper(ll_finalizer, [llmemory.Address], lltype.Void) + fptr = self.annotate_helper(ll_finalizer, [llmemory.Address], lltype.Void) else: - g = fptr = lltype.nullptr(ADDRESS_VOID_FUNC) - if g: - self.need_minimal_transform(g) + fptr = lltype.nullptr(ADDRESS_VOID_FUNC) + self.finalizer_funcptrs[TYPE] = fptr return fptr @@ -1085,56 +1077,53 @@ self.offsettable_cache[TYPE] = cachedarray return cachedarray - def finish(self): - finished = self.finished - newgcdependencies = super(FrameworkGCTransformer, self).finish() - if not finished: - - table = lltype.malloc(self.gcdata.TYPE_INFO_TABLE, - len(self.type_info_list), immortal=True) - for tableentry, newcontent in zip(table, self.type_info_list): - for key, value in newcontent.items(): - setattr(tableentry, key, value) - self.offsettable_cache = None - - # replace the type_info_table pointer in gcdata -- at this point, - # the database is in principle complete, so it has already seen - # the old (empty) array. We need to force it to consider the new - # array now. It's a bit hackish as the old empty array will also - # be generated in the C source, but that's a rather minor problem. - - # XXX because we call inputconst already in replace_malloc, we can't - # modify the instance, we have to modify the 'rtyped instance' - # instead. horrors. is there a better way? - - s_gcdata = self.translator.annotator.bookkeeper.immutablevalue( - self.gcdata) - r_gcdata = self.translator.rtyper.getrepr(s_gcdata) - ll_instance = rmodel.inputconst(r_gcdata, self.gcdata).value - ll_instance.inst_type_info_table = table - #self.gcdata.type_info_table = table - - ll_static_roots = lltype.malloc(lltype.Array(llmemory.Address), - len(self.static_gc_roots) + - self.extra_static_slots, - immortal=True) - for i in range(len(self.static_gc_roots)): - adr = self.static_gc_roots[i] - ll_static_roots[i] = adr - ll_instance.inst_static_roots = ll_static_roots - - ll_static_roots_inside = lltype.malloc(lltype.Array(llmemory.Address), - len(self.addresses_of_static_ptrs_in_nongc), - immortal=True) - for i in range(len(self.addresses_of_static_ptrs_in_nongc)): - ll_static_roots_inside[i] = self.addresses_of_static_ptrs_in_nongc[i] - ll_instance.inst_static_root_start = llmemory.cast_ptr_to_adr(ll_static_roots_inside) + llmemory.ArrayItemsOffset(lltype.Array(llmemory.Address)) - ll_instance.inst_static_root_end = ll_instance.inst_static_root_start + llmemory.sizeof(llmemory.Address) * len(ll_static_roots_inside) - - newgcdependencies = newgcdependencies or [] - newgcdependencies.append(table) - newgcdependencies.append(ll_static_roots) - newgcdependencies.append(ll_static_roots_inside) + def finish_tables(self): + self.finished_tables = True + table = lltype.malloc(self.gcdata.TYPE_INFO_TABLE, + len(self.type_info_list), immortal=True) + for tableentry, newcontent in zip(table, self.type_info_list): + for key, value in newcontent.items(): + setattr(tableentry, key, value) + self.offsettable_cache = None + + # replace the type_info_table pointer in gcdata -- at this point, + # the database is in principle complete, so it has already seen + # the old (empty) array. We need to force it to consider the new + # array now. It's a bit hackish as the old empty array will also + # be generated in the C source, but that's a rather minor problem. + + # XXX because we call inputconst already in replace_malloc, we can't + # modify the instance, we have to modify the 'rtyped instance' + # instead. horrors. is there a better way? + + s_gcdata = self.translator.annotator.bookkeeper.immutablevalue( + self.gcdata) + r_gcdata = self.translator.rtyper.getrepr(s_gcdata) + ll_instance = rmodel.inputconst(r_gcdata, self.gcdata).value + ll_instance.inst_type_info_table = table + #self.gcdata.type_info_table = table + + ll_static_roots = lltype.malloc(lltype.Array(llmemory.Address), + len(self.static_gc_roots) + + self.extra_static_slots, + immortal=True) + for i in range(len(self.static_gc_roots)): + adr = self.static_gc_roots[i] + ll_static_roots[i] = adr + ll_instance.inst_static_roots = ll_static_roots + + ll_static_roots_inside = lltype.malloc(lltype.Array(llmemory.Address), + len(self.addresses_of_static_ptrs_in_nongc), + immortal=True) + for i in range(len(self.addresses_of_static_ptrs_in_nongc)): + ll_static_roots_inside[i] = self.addresses_of_static_ptrs_in_nongc[i] + ll_instance.inst_static_root_start = llmemory.cast_ptr_to_adr(ll_static_roots_inside) + llmemory.ArrayItemsOffset(lltype.Array(llmemory.Address)) + ll_instance.inst_static_root_end = ll_instance.inst_static_root_start + llmemory.sizeof(llmemory.Address) * len(ll_static_roots_inside) + + newgcdependencies = [] + newgcdependencies.append(table) + newgcdependencies.append(ll_static_roots) + newgcdependencies.append(ll_static_roots_inside) return newgcdependencies def protect_roots(self, op, livevars, block, index=-1): Modified: pypy/dist/pypy/rpython/memory/test/test_transformed_gc.py ============================================================================== --- pypy/dist/pypy/rpython/memory/test/test_transformed_gc.py (original) +++ pypy/dist/pypy/rpython/memory/test/test_transformed_gc.py Tue May 23 16:41:19 2006 @@ -389,10 +389,10 @@ self.id = b.nextid b.nextid += 1 def __del__(self): + llop.gc__collect(lltype.Void) b.num_deleted += 1 C() C() - llop.gc__collect(lltype.Void) class C(A): def __del__(self): b.num_deleted += 1 Modified: pypy/dist/pypy/translator/c/database.py ============================================================================== --- pypy/dist/pypy/translator/c/database.py (original) +++ pypy/dist/pypy/translator/c/database.py Tue May 23 16:41:19 2006 @@ -30,7 +30,8 @@ self.pendingsetupnodes = [] self.containernodes = {} self.containerlist = [] - self.latercontainerlist = [] + self.delayedfunctionnames = {} + self.delayedfunctionptrs = [] self.completedcontainers = 0 self.containerstats = {} self.externalfuncs = {} @@ -138,7 +139,7 @@ else: raise Exception("don't know about type %r" % (T,)) - def getcontainernode(self, container): + def getcontainernode(self, container, **buildkwds): try: node = self.containernodes[container] except KeyError: @@ -148,12 +149,9 @@ if hasattr(self.gctransformer, 'consider_constant'): self.gctransformer.consider_constant(T, container) nodefactory = ContainerNodeFactory[T.__class__] - node = nodefactory(self, T, container) + node = nodefactory(self, T, container, **buildkwds) self.containernodes[container] = node - if node.is_later_container: - self.latercontainerlist.append(node) - else: - self.containerlist.append(node) + self.containerlist.append(node) kind = getattr(node, 'nodekind', '?') self.containerstats[kind] = self.containerstats.get(kind, 0) + 1 return node @@ -173,11 +171,40 @@ return PrimitiveName[T](obj, self) elif isinstance(T, Ptr): if obj: # test if the ptr is non-NULL - if isinstance(obj._obj, int): + try: + container = obj._obj + except lltype.DelayedPointer: + # hack hack hack + name = obj._obj0 + assert name.startswith('delayed!') + n = len('delayed!') + if len(name) == n: + raise + if id(obj) in self.delayedfunctionnames: + return self.delayedfunctionnames[id(obj)][0] + funcname = name[n:] + funcname = self.namespace.uniquename('g_' + funcname) + self.delayedfunctionnames[id(obj)] = funcname, obj + self.delayedfunctionptrs.append(obj) + return funcname + # /hack hack hack + else: + # hack hack hack + if id(obj) in self.delayedfunctionnames: + # this used to be a delayed function, + # make sure we use the same name + forcename = self.delayedfunctionnames[id(obj)][0] + node = self.getcontainernode(container, + forcename=forcename) + assert node.ptrname == forcename + return forcename + # /hack hack hack + + if isinstance(container, int): # special case for tagged odd-valued pointers return '((%s) %d)' % (cdecl(self.gettype(T), ''), obj._obj) - node = self.getcontainernode(obj._obj) + node = self.getcontainernode(container) return node.ptrname else: return '((%s) NULL)' % (cdecl(self.gettype(T), ''), ) @@ -198,10 +225,52 @@ show_i = (i//1000 + 1) * 1000 else: show_i = -1 - work_to_do = True - transformations_to_finish = [self.gctransformer] + + # The order of database completion is fragile with stackless and + # gc transformers. Here is what occurs: + # + # 1. follow dependencies recursively from the entry point: data + # structures pointing to other structures or functions, and + # constants in functions pointing to other structures or functions. + # Because of the mixlevelannotator, this might find delayed + # (not-annotated-and-rtyped-yet) function pointers. They are + # not followed at this point. User finalizers (__del__) on the + # other hand are followed during this step too. + # + # 2. gctransformer.finish_helpers() - after this, all functions in + # the program have been rtyped. + # + # 3. follow new dependencies. All previously delayed functions + # should have been resolved by 2 - they are gc helpers, like + # ll_finalize(). New FuncNodes are built for them. No more + # FuncNodes can show up after this step. + # + # 4. stacklesstransform.finish() - freeze the stackless resume point + # table. + # + # 5. follow new dependencies (this should be only the new frozen + # table, which contains only numbers and already-seen function + # pointers). + # + # 6. gctransformer.finish_tables() - freeze the gc types table. + # + # 7. follow new dependencies (this should be only the gc type table, + # which contains only numbers and pointers to ll_finalizer + # functions seen in step 3). + # + # I think that there is no reason left at this point that force + # step 4 to be done before step 6, nor to have a follow-new- + # dependencies step inbetween. It is important though to have step 3 + # before steps 4 and 6. + # + # This is implemented by interleaving the follow-new-dependencies + # steps with calls to the next 'finish' function from the following + # list: + finish_callbacks = [] + finish_callbacks.append(self.gctransformer.finish_helpers) if self.stacklesstransformer: - transformations_to_finish.insert(0, self.stacklesstransformer) + finish_callbacks.append(self.stacklesstransformer.finish) + finish_callbacks.append(self.gctransformer.finish_tables) def add_dependencies(newdependencies): for value in newdependencies: @@ -210,7 +279,7 @@ else: self.get(value) - while work_to_do: + while True: while True: if hasattr(self, 'pyobjmaker'): self.pyobjmaker.collect_initcode() @@ -228,22 +297,32 @@ if i == show_i: dump() show_i += 1000 - work_to_do = False - while transformations_to_finish: - transformation = transformations_to_finish.pop(0) - newdependencies = transformation.finish() + if self.delayedfunctionptrs: + lst = self.delayedfunctionptrs + self.delayedfunctionptrs = [] + progress = False + for fnptr in lst: + try: + fnptr._obj + except lltype.DelayedPointer: # still not resolved + self.delayedfunctionptrs.append(fnptr) + else: + self.get(fnptr) + progress = True + if progress: + continue # progress - follow all dependencies again + + if finish_callbacks: + finish = finish_callbacks.pop(0) + newdependencies = finish() if newdependencies: add_dependencies(newdependencies) - work_to_do = True - break - else: - if self.latercontainerlist: - work_to_do = True - for node in self.latercontainerlist: - node.make_funcgens() - self.containerlist.append(node) - self.latercontainerlist = [] + continue # progress - follow all dependencies again + + break # database is now complete + + assert not self.delayedfunctionptrs self.completed = True if show_progress: dump() Modified: pypy/dist/pypy/translator/c/funcgen.py ============================================================================== --- pypy/dist/pypy/translator/c/funcgen.py (original) +++ pypy/dist/pypy/translator/c/funcgen.py Tue May 23 16:41:19 2006 @@ -10,6 +10,7 @@ from pypy.rpython.lltypesystem.lltype import UnsignedLongLong, Char, UniChar from pypy.rpython.lltypesystem.lltype import pyobjectptr, ContainerType from pypy.rpython.lltypesystem.lltype import Struct, Array, FixedSizeArray +from pypy.rpython.lltypesystem.lltype import ForwardReference from pypy.translator.backendopt.ssa import SSI_to_SSA PyObjPtr = Ptr(PyObject) @@ -34,15 +35,14 @@ blocknum oldgraph""".split() - def __init__(self, graph, db, cpython_exc=False, functionname=None, - do_stackless=True): + def __init__(self, graph, db, cpython_exc=False, functionname=None): self.graph = graph self.db = db self.gcpolicy = db.gcpolicy self.cpython_exc = cpython_exc self.functionname = functionname # apply the stackless transformation - if db.stacklesstransformer and do_stackless: + if db.stacklesstransformer: db.stacklesstransformer.transform_graph(graph) # apply the exception transformation if self.db.exctransformer: @@ -54,6 +54,10 @@ for v in self.vars: T = getattr(v, 'concretetype', PyObjPtr) + # obscure: skip forward references and hope for the best + # (needed for delayed function pointers) + if isinstance(T, Ptr) and T.TO.__class__ == ForwardReference: + continue db.gettype(T) # force the type to be considered by the database self.lltypes = None Modified: pypy/dist/pypy/translator/c/gc.py ============================================================================== --- pypy/dist/pypy/translator/c/gc.py (original) +++ pypy/dist/pypy/translator/c/gc.py Tue May 23 16:41:19 2006 @@ -355,7 +355,7 @@ if rtti is not None and hasattr(rtti._obj, 'destructor_funcptr'): destrptr = rtti._obj.destructor_funcptr # make sure this is seen by the database early, i.e. before - # finish() on the gctransformer + # finish_helpers() on the gctransformer self.db.get(destrptr) def array_setup(self, arraydefnode): Modified: pypy/dist/pypy/translator/c/node.py ============================================================================== --- pypy/dist/pypy/translator/c/node.py (original) +++ pypy/dist/pypy/translator/c/node.py Tue May 23 16:41:19 2006 @@ -335,7 +335,6 @@ class ContainerNode(object): - is_later_container = False if USESLOTS: __slots__ = """db T obj typename implementationtypename @@ -544,20 +543,18 @@ # there not so many node of this kind, slots should not # be necessary - def __init__(self, db, T, obj): + def __init__(self, db, T, obj, forcename=None): self.globalcontainer = True self.db = db self.T = T self.obj = obj if hasattr(obj, 'includes'): self.includes = obj.includes - self.name = self.basename() - else: - self.name = db.namespace.uniquename('g_' + self.basename()) - if not getattr(obj, 'isgchelper', False): - self.make_funcgens() + self.name = forcename or self.basename() else: - self.is_later_container = True + self.name = (forcename or + db.namespace.uniquename('g_' + self.basename())) + self.make_funcgens() #self.dependencies = {} self.typename = db.gettype(T) #, who_asks=self) self.ptrname = self.name @@ -656,8 +653,7 @@ from pypy.translator.c.stackless import SlpFunctionCodeGenerator return [SlpFunctionCodeGenerator(fnobj.graph, db, cpython_exc, functionname)] else: - return [FunctionCodeGenerator(fnobj.graph, db, cpython_exc, functionname, - do_stackless = not getattr(fnobj, 'isgchelper', False))] + return [FunctionCodeGenerator(fnobj.graph, db, cpython_exc, functionname)] elif getattr(fnobj, 'external', None) == 'C': # deprecated case if hasattr(fnobj, 'includes'): From arigo at codespeak.net Tue May 23 16:54:30 2006 From: arigo at codespeak.net (arigo at codespeak.net) Date: Tue, 23 May 2006 16:54:30 +0200 (CEST) Subject: [pypy-svn] r27623 - pypy/dist/pypy/translator/c Message-ID: <20060523145430.69DDC1005A@code0.codespeak.net> Author: arigo Date: Tue May 23 16:54:29 2006 New Revision: 27623 Modified: pypy/dist/pypy/translator/c/gc.py Log: Missing from the previous check-in. Modified: pypy/dist/pypy/translator/c/gc.py ============================================================================== --- pypy/dist/pypy/translator/c/gc.py (original) +++ pypy/dist/pypy/translator/c/gc.py Tue May 23 16:54:29 2006 @@ -357,6 +357,13 @@ # make sure this is seen by the database early, i.e. before # finish_helpers() on the gctransformer self.db.get(destrptr) + # the following, on the other hand, will only discover ll_finalizer + # helpers. The get() sees and records a delayed pointer. It is + # still important to see it so that it can be followed as soon as + # the mixlevelannotator resolves it. + gctransf = self.db.gctransformer + fptr = gctransf.finalizer_funcptr_for_type(structdefnode.STRUCT) + self.db.get(fptr) def array_setup(self, arraydefnode): pass From arigo at codespeak.net Tue May 23 17:32:10 2006 From: arigo at codespeak.net (arigo at codespeak.net) Date: Tue, 23 May 2006 17:32:10 +0200 (CEST) Subject: [pypy-svn] r27624 - pypy/dist/pypy/objspace/std Message-ID: <20060523153210.E4D3610061@code0.codespeak.net> Author: arigo Date: Tue May 23 17:32:09 2006 New Revision: 27624 Modified: pypy/dist/pypy/objspace/std/unicodeobject.py pypy/dist/pypy/objspace/std/unicodetype.py Log: This 'import codecs' caused geninterp to freeze a codecs function from the ambiant stdlib into the _cache! Crash with 2.5 where its body changed to accomodate for a change in _codecs that our own 2.4-compatible _codecs does not provide. Modified: pypy/dist/pypy/objspace/std/unicodeobject.py ============================================================================== --- pypy/dist/pypy/objspace/std/unicodeobject.py (original) +++ pypy/dist/pypy/objspace/std/unicodeobject.py Tue May 23 17:32:09 2006 @@ -510,6 +510,7 @@ try: w_unichar = unicodetype.unicode_from_object(space, w_char) except OperationError: + # XXX don't completely eat this exception raise OperationError(space.w_TypeError, space.wrap('The fill character cannot be converted to Unicode')) if space.int_w(space.len(w_unichar)) != 1: Modified: pypy/dist/pypy/objspace/std/unicodetype.py ============================================================================== --- pypy/dist/pypy/objspace/std/unicodetype.py (original) +++ pypy/dist/pypy/objspace/std/unicodetype.py Tue May 23 17:32:09 2006 @@ -45,9 +45,8 @@ # ____________________________________________________________ app = gateway.applevel(''' -import codecs, sys - def unicode_from_encoded_object(obj, encoding, errors): + import codecs, sys if encoding is None: encoding = sys.getdefaultencoding() decoder = codecs.getdecoder(encoding) From ale at codespeak.net Tue May 23 17:43:46 2006 From: ale at codespeak.net (ale at codespeak.net) Date: Tue, 23 May 2006 17:43:46 +0200 (CEST) Subject: [pypy-svn] r27625 - pypy/dist/pypy/lib/pyontology Message-ID: <20060523154346.7B45110061@code0.codespeak.net> Author: ale Date: Tue May 23 17:43:44 2006 New Revision: 27625 Modified: pypy/dist/pypy/lib/pyontology/constraint_classes.py pypy/dist/pypy/lib/pyontology/pyontology.py Log: Fixes for Nothing Modified: pypy/dist/pypy/lib/pyontology/constraint_classes.py ============================================================================== --- pypy/dist/pypy/lib/pyontology/constraint_classes.py (original) +++ pypy/dist/pypy/lib/pyontology/constraint_classes.py Tue May 23 17:43:44 2006 @@ -25,16 +25,31 @@ class CardinalityConstraint(AbstractConstraint): + cost = 10 + def __init__(self, prop, cls_name, var, comp): AbstractConstraint.__init__(self, [prop]) self.check_individual = "domains['%s'].getValues() != []" % prop self.formula = "len(domains['%s'].getValuesPrKey('%s')) %s int(%s)"% (prop, cls_name, comp, var) + def estimateCost(self, domains): + return self.cost + def narrow(self, domains): if eval(self.check_individual): if not eval(self.formula): raise ConsistencyFailure +class NothingConstraint(AbstractConstraint): + + def __init__(self, variable): + AbstractConstraint.__init__(self, [variable]) + self.variable = variable + + def narrow(self, domains): + if domains[self.variable] != []: + raise ConsistencyFailure + class SubClassConstraint(AbstractConstraint): cost=1 @@ -63,6 +78,8 @@ class DisjointClassConstraint(SubClassConstraint): def narrow(self, domains): + if self.variable ==self.object: + raise ConsistencyFailure subdom = domains[self.variable] superdom = domains[self.object] vals1 = superdom.getValues() Modified: pypy/dist/pypy/lib/pyontology/pyontology.py ============================================================================== --- pypy/dist/pypy/lib/pyontology/pyontology.py (original) +++ pypy/dist/pypy/lib/pyontology/pyontology.py Tue May 23 17:43:44 2006 @@ -19,6 +19,7 @@ Class = URIRef(u'http://www.w3.org/2002/07/owl#Class') Thing_uri = URIRef(u'http://www.w3.org/2002/07/owl#Thing') +Nothing_uri = URIRef(u'http://www.w3.org/2002/07/owl#Nothing') rdf_type = URIRef(u'http://www.w3.org/1999/02/22-rdf-syntax-ns#type') rdf_rest = URIRef(u'http://www.w3.org/1999/02/22-rdf-syntax-ns#rest') rdf_first = URIRef(u'http://www.w3.org/1999/02/22-rdf-syntax-ns#first') @@ -171,9 +172,10 @@ pass class Nothing(ClassDomain): - - pass + def __init__(self, name='', values=[], bases = []): + ClassDomain.__init__(self, name, values, bases) + self.constraint = NothingConstraint(name) class FunctionalProperty(Property): @@ -334,6 +336,8 @@ self.consider_triple(triple) def make_var(self, cls=fd, a=''): + if a in builtin_voc: + cls = builtin_voc[a] if type(a) == URIRef: if a.find('#') != -1: ns,name = a.split('#') @@ -371,11 +375,13 @@ raise ConsistencyFailure equal = val - if mini and maxi and (mini > maxi or - equal < mini or - equal > maxi): + if mini and maxi and mini > maxi: raise ConsistencyFailure - + if mini and equal and equal < mini: + raise ConsistencyFailure + if maxi and equal and equal > maxi: + raise ConsistencyFailure + def check_TBoxes(self): for var, cls in self.variables.items(): for prop, terms in cls.TBox.items(): @@ -438,7 +444,8 @@ cls = self.variables[svar] if hasattr(cls, 'constraint'): self.constraints.append(cls.constraint) - self.variables[avar].addValue(s) + if not isinstance(self.variables[avar], Property): + self.variables[avar].addValue(s) def first(self, s, var): pass @@ -490,6 +497,8 @@ self.subClassOf(var, s) def disjointWith(self, s, var): + self.resolve_item(s) + self.resolve_item(var) avar = self.make_var(None, var) svar = self.make_var(None, s) constrain = DisjointClassConstraint(svar, avar) @@ -527,7 +536,10 @@ res = [] for val in vals: - res.extend([x for x in val]) + self.get_individuals_of(val) + var_name = self.make_var(ClassDomain, val) + val = self.variables[var_name].getValues() + res.extend([x for x in val]) svar = self.make_var(ClassDomain, s) vals = self.variables[svar].getValues() res.extend(vals) @@ -535,12 +547,13 @@ def intersectionOf(self, s, var): var = self.flatten_rdf_list(var) - vals = self.variables[var].getValues() + vals = [self.make_var(ClassDomain, x) for x in self.variables[var].getValues()] + res = vals[0] for l in vals[1:]: result = [] for v in res: - if v in l : + if v in self.variables[l].getValues() : result.append(v) res = result svar = self.make_var(ClassDomain, s) @@ -563,7 +576,8 @@ def subPropertyOf(self, s, var): # s is a subproperty of var - self.resolve_item(var) + self.resolve_predicate(var) + self.resolve_predicate(s) avar = self.make_var(Property, var) svar = self.make_var(Property, s) avals = self.variables[avar].getValues() From arigo at codespeak.net Tue May 23 18:16:02 2006 From: arigo at codespeak.net (arigo at codespeak.net) Date: Tue, 23 May 2006 18:16:02 +0200 (CEST) Subject: [pypy-svn] r27626 - in pypy/dist/pypy/rpython: . test Message-ID: <20060523161602.B547E10068@code0.codespeak.net> Author: arigo Date: Tue May 23 18:16:01 2006 New Revision: 27626 Modified: pypy/dist/pypy/rpython/rtuple.py pypy/dist/pypy/rpython/test/test_rtuple.py Log: Fix&test for constant tuples with void items. Modified: pypy/dist/pypy/rpython/rtuple.py ============================================================================== --- pypy/dist/pypy/rpython/rtuple.py (original) +++ pypy/dist/pypy/rpython/rtuple.py Tue May 23 18:16:01 2006 @@ -111,7 +111,8 @@ p = self.instantiate() self.tuple_cache[key] = p for obj, r, name in zip(value, self.items_r, self.fieldnames): - setattr(p, name, r.convert_const(obj)) + if r.lowleveltype is not Void: + setattr(p, name, r.convert_const(obj)) return p def compact_repr(self): 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 May 23 18:16:01 2006 @@ -230,6 +230,19 @@ res = self.interpret(g, [3]) assert res == 3 + def test_void_items(self): + def f(): + return 6 + def getf(): + return f + def g(): + f1 = getf() + return (f1, 12) + def example(): + return g()[0]() + res = self.interpret(example, []) + assert res == 6 + class TestLLtype(BaseTestRtuple, LLRtypeMixin): pass From arigo at codespeak.net Tue May 23 18:24:04 2006 From: arigo at codespeak.net (arigo at codespeak.net) Date: Tue, 23 May 2006 18:24:04 +0200 (CEST) Subject: [pypy-svn] r27627 - in pypy/dist/pypy/translator/stackless: . test Message-ID: <20060523162404.4FBAD10061@code0.codespeak.net> Author: arigo Date: Tue May 23 18:24:03 2006 New Revision: 27627 Modified: pypy/dist/pypy/translator/stackless/test/test_transform.py pypy/dist/pypy/translator/stackless/transform.py Log: Fix for Void variables that are passed around and used later. (This is a rare situation, so it didn't show up before.) Modified: pypy/dist/pypy/translator/stackless/test/test_transform.py ============================================================================== --- pypy/dist/pypy/translator/stackless/test/test_transform.py (original) +++ pypy/dist/pypy/translator/stackless/test/test_transform.py Tue May 23 18:24:03 2006 @@ -226,6 +226,21 @@ if op.args[0].value._obj._callable is f: assert op != block.operations[-1] +def test_void_around(): + def f(): + return 6 + def getf(): + return f + def g(): + f1 = getf() + for i in range(5): + rstack.stack_unwind() + return f1 + def example(): + return g()() + res = llinterp_stackless_function(example) + assert res == 6 + def rtype_stackless_function(fn): t = TranslationContext() annotator = t.buildannotator() Modified: pypy/dist/pypy/translator/stackless/transform.py ============================================================================== --- pypy/dist/pypy/translator/stackless/transform.py (original) +++ pypy/dist/pypy/translator/stackless/transform.py Tue May 23 18:24:03 2006 @@ -320,11 +320,13 @@ assert arg is not resume_point.var_result t = storage_type(arg.concretetype) if t is lltype.Void: - continue - fname = model.Constant(resume_point.fieldnames[i], lltype.Void) - v_newarg = llops.genop('getfield', [frame_top, fname], - resulttype = t) - v_newarg = gen_cast(llops, arg.concretetype, v_newarg) + v_newarg = model.Constant(None, lltype.Void) + else: + fname = model.Constant(resume_point.fieldnames[i], + lltype.Void) + v_newarg = llops.genop('getfield', [frame_top, fname], + resulttype = t) + v_newarg = gen_cast(llops, arg.concretetype, v_newarg) varmap[arg] = v_newarg rettype = storage_type(resume_point.var_result.concretetype) @@ -460,7 +462,6 @@ for l in block.exits: for arg in l.args: if isinstance(arg, model.Variable) \ - and arg.concretetype is not lltype.Void \ and arg is not op.result \ and arg not in args \ and arg not in [l.last_exception, l.last_exc_value]: From arigo at codespeak.net Tue May 23 18:37:07 2006 From: arigo at codespeak.net (arigo at codespeak.net) Date: Tue, 23 May 2006 18:37:07 +0200 (CEST) Subject: [pypy-svn] r27628 - pypy/dist/pypy/translator/stackless Message-ID: <20060523163707.E92F310061@code0.codespeak.net> Author: arigo Date: Tue May 23 18:37:07 2006 New Revision: 27628 Modified: pypy/dist/pypy/translator/stackless/frame.py Log: Add WeakGcAddress support in the stackless transformer. Tests were already checked in (and failing!): test_framework_weakref* in newgc. Modified: pypy/dist/pypy/translator/stackless/frame.py ============================================================================== --- pypy/dist/pypy/translator/stackless/frame.py (original) +++ pypy/dist/pypy/translator/stackless/frame.py Tue May 23 18:37:07 2006 @@ -14,13 +14,15 @@ null_saved_ref = lltype.nullptr(SAVED_REFERENCE.TO) STORAGE_TYPES = [lltype.Void, SAVED_REFERENCE, llmemory.Address, - lltype.Signed, lltype.Float, lltype.SignedLongLong] + lltype.Signed, lltype.Float, lltype.SignedLongLong, + llmemory.WeakGcAddress] STORAGE_FIELDS = {SAVED_REFERENCE: 'ref', llmemory.Address: 'addr', lltype.Signed: 'long', lltype.Float: 'float', lltype.SignedLongLong: 'longlong', + llmemory.WeakGcAddress: 'weak', } RETVAL_VOID = 0 @@ -43,6 +45,8 @@ return lltype.SignedLongLong elif T is llmemory.Address: return llmemory.Address + elif T is llmemory.WeakGcAddress: + return llmemory.WeakGcAddress elif isinstance(T, lltype.Primitive): return lltype.Signed else: From tismer at codespeak.net Tue May 23 21:57:41 2006 From: tismer at codespeak.net (tismer at codespeak.net) Date: Tue, 23 May 2006 21:57:41 +0200 (CEST) Subject: [pypy-svn] r27629 - in pypy/dist/pypy/translator: c c/test tool Message-ID: <20060523195741.DFA4410064@code0.codespeak.net> Author: tismer Date: Tue May 23 21:57:36 2006 New Revision: 27629 Added: pypy/dist/pypy/translator/tool/raymond.py (contents, props changed) Modified: pypy/dist/pypy/translator/c/pyobj.py pypy/dist/pypy/translator/c/test/test_wrapping.py Log: (chris, richard) initial version of the raymond module. also found a bad bug that was hiding, before. Richard, thank you so much for nagging until I found it :-) Modified: pypy/dist/pypy/translator/c/pyobj.py ============================================================================== --- pypy/dist/pypy/translator/c/pyobj.py (original) +++ pypy/dist/pypy/translator/c/pyobj.py Tue May 23 21:57:36 2006 @@ -542,7 +542,6 @@ # addition for true extension module building def wrap_exported_class(self, cls): - metaclass = "type" name = self.uniquename('gwcls_' + cls.__name__) basenames = [self.nameof(base) for base in cls.__bases__] # we merge the class dicts for more speed @@ -612,7 +611,8 @@ def nameof_graph(self, g): newname=self.name_for_meth.get(g, g.func.__name__) - fwrapper = gen_wrapper(g, self.translator, newname=newname) + fwrapper = gen_wrapper(g, self.translator, newname=newname, + as_method=g in self.is_method) pycfunctionobj = self.uniquename('gfunc_' + newname) self.wrappers[pycfunctionobj] = g.func.__name__, self.getvalue(fwrapper), g.func.__doc__ return pycfunctionobj Modified: pypy/dist/pypy/translator/c/test/test_wrapping.py ============================================================================== --- pypy/dist/pypy/translator/c/test/test_wrapping.py (original) +++ pypy/dist/pypy/translator/c/test/test_wrapping.py Tue May 23 21:57:36 2006 @@ -1,177 +1,11 @@ -from pypy.translator.translator import TranslationContext -from pypy import conftest -from py.test import raises -from pypy.rpython.extregistry import ExtRegistryEntry -from pypy.annotation import model as annmodel -from pypy.rpython.lltypesystem import lltype -from pypy.rpython import robject, rclass, rint -from pypy.translator.tool.cbuild import enable_fast_compilation -from pypy.interpreter.baseobjspace import ObjSpace +from pypy.translator.tool.raymond import (get_compiled_module, get_compiled, + wrap, unwrap, __init__, + ExtCompiler) import sys, types P = False # debug printing -SPECIAL_METHODS = {} - -def setup_special_methods(): - for name, op, arity, funcs in ObjSpace.MethodTable: - for fname in funcs: - if fname.startswith('__'): - ann = [None] * arity # replaced by class - if 'attr' in fname: - ann[1] = str - elif 'item' in fname: - ann[1] = int - elif 'pow' in fname: - ann[1] = int - elif 'shift' in fname: - ann[1] = int - if arity == 3 and '_set' in fname: - ann[-1] = object - SPECIAL_METHODS[fname] = ann -setup_special_methods() - -def get_annotation(func, pre=[]): - argstypelist = pre[:] - if func.func_defaults: - for spec in func.func_defaults: - if isinstance(spec, tuple): - # use the first type only for the tests - spec = spec[0] - argstypelist.append(spec) - elif len(argstypelist) == 1: - argstypelist = guess_methannotation(func, argstypelist[0]) - missing = [object] * (func.func_code.co_argcount - len(argstypelist)) - return missing + argstypelist - -def guess_methannotation(func, cls): - ret = [cls] - if func.__name__ in SPECIAL_METHODS: - pattern = SPECIAL_METHODS[func.__name__] - ret = [thetype or cls for thetype in pattern] - return ret - -def get_compiled_module(func, view=conftest.option.view, inline_threshold=1, - use_boehm=False, exports=None): - from pypy.translator.translator import TranslationContext - from pypy.translator.backendopt.all import backend_optimizations - - from pypy.translator.c import gc - from pypy.translator.c.genc import CExtModuleBuilder - - global _t # allow us to view later - _t = t = TranslationContext(do_imports_immediately=False) - ann = t.buildannotator() - rtyper = t.buildrtyper() - bk = rtyper.annotator.bookkeeper - if not exports: - exports = [] - all = [obj.__name__ for obj in exports if obj.__name__ != '__init__'] - exports = exports + [('__all__', all)] - - ann.build_types(func, get_annotation(func)) - - pyobj_options = {} - - for obj in exports: - if isinstance(obj, type): - cls = obj - clsdef = bk.getuniqueclassdef(cls) - rtyper.add_wrapper(clsdef) - for obj in cls.__dict__.values(): - if isinstance(obj, types.FunctionType): - if not ann.bookkeeper.getdesc(obj).querycallfamily(): - # not annotated, so enforce it - ann.build_types(obj, get_annotation(obj, [cls]), complete_now=False) - elif isinstance(obj, property): - for obj in obj.fget, obj.fset, obj.fdel: - if obj and not ann.bookkeeper.getdesc(obj).querycallfamily(): - ann.build_types(obj, get_annotation(obj, [cls]), complete_now=False) - elif isinstance(obj, types.FunctionType): - if not ann.bookkeeper.getdesc(obj).querycallfamily(): - # not annotated, so enforce it - ann.build_types(obj, get_annotation(obj), complete_now=False) - if obj.__name__ == '__init__': - pyobj_options['use_true_methods'] = True - - ann.build_types(func, get_annotation(func)) - if view: - t.viewcg() - rtyper.specialize() - if view: - t.viewcg() - t.checkgraphs() - - gcpolicy = None - if use_boehm: - gcpolicy = gc.BoehmGcPolicy - - backend_optimizations(t, inline_threshold=inline_threshold) - if view: - t.viewcg() - - cbuilder = CExtModuleBuilder(t, func, gcpolicy=gcpolicy) - # explicit build of database - db = cbuilder.build_database(exports=exports, pyobj_options=pyobj_options) - cbuilder.generate_source(db) - if view: - t.viewcg() - cbuilder.compile() - - return cbuilder.import_module() - -def getcompiled(func, *args, **kwds): - module = get_compiled_module(func, *args, **kwds) - return getattr(module, func.__name__) - -# _______________________________________________- -# stubs for special annotation/rtyping - - -def wrap(thing): - return thing # untranslated case - -def unwrap(pyobj, typ): - assert isinstance(pyobj, typ) - return pyobj # untranslated case -unwrap._annspecialcase_ = 'specialize:arg(1)' - - -# XXX -# wrapping/unwrapping should be annotatable. -# Idea: create tunnel objects which share -# annotation across SomeObjectness, sharing a key! - -class Entry(ExtRegistryEntry): - _about_ = unwrap - - def compute_result_annotation(self, s_wrapped, s_spec): - # this will go away, much better way found! - assert hasattr(s_spec, 'descriptions'), 'need a class in unwrap 2nd arg' - descs = s_spec.descriptions - assert len(descs) == 1, 'missing specialisation, classdesc not unique!' - for desc in descs.keys(): - classdef = desc.getuniqueclassdef() - return annmodel.SomeInstance(classdef) - - def specialize_call(self, hop): - v_obj = hop.inputarg(hop.args_r[0], 0) - return hop.llops.convertvar(v_obj, hop.args_r[0], hop.r_result) - - -class Entry(ExtRegistryEntry): - _about_ = wrap - - s_result_annotation = annmodel.SomeObject() - - def specialize_call(self, hop): - assert len(hop.args_r) == 1, 'wrap() takes exactly one argument' - v_obj, = hop.inputargs(*hop.args_r) - return hop.llops.convertvar(v_obj, hop.args_r[0], robject.pyobj_repr) - -# _______________________________________________- -# the actual tests # track __del__ calls class DelMonitor(object): @@ -266,119 +100,9 @@ self2 = DemoSubclass(a, b, 42) return self -# _______________________________________________ -# creating our own setup function for the module - -# this class *can* be used for faster access. -# the compiler anyway chews quite a bit on it... -class BuiltinHelper(object): - # the following would be much easier if we had - # loop unrolling right inside the flowing process - src = [] - src.append('def __init__(self):') - src.append(' import __builtin__ as b') - import __builtin__ - for name in dir(__builtin__): - obj = getattr(__builtin__, name) - if callable(obj) and hasattr(obj, '__name__'): - src.append(' self.%s = b.%s' % (name, obj.__name__)) - src = '\n'.join(src) - #print src - exec src - del __builtin__, name, obj, src - - -def get_methodname(funcidx): - pass - -class Entry(ExtRegistryEntry): - _about_ = get_methodname - s_result_annotation = annmodel.SomeObject() - - def specialize_call(self, hop): - v_idx, = hop.inputargs(*hop.args_r) - if hop.args_r[0] <> rint.signed_repr: - v_idx = hop.llops.convertvar(v_idx, - r_from=hop.args_r[0], - r_to=rint.signed_repr) - v_res = hop.llops.gencapicall('postsetup_get_methodname', [v_idx], - resulttype=robject.pyobj_repr) - return v_res - -def build_method(funcidx): - pass - -class Entry(ExtRegistryEntry): - _about_ = build_method - s_result_annotation = annmodel.SomeObject() - - def specialize_call(self, hop): - v_idx, v_type = hop.inputargs(*hop.args_r) - if hop.args_r[0] <> rint.signed_repr: - v_idx = hop.llops.convertvar(v_idx, - r_from=hop.args_r[0], - r_to=rint.signed_repr) - assert hop.args_r[1] == robject.pyobj_repr, ( - 'build_method works for Python types only') - v_res = hop.llops.gencapicall('postsetup_build_method', [v_idx, v_type], - resulttype=robject.pyobj_repr) - return v_res - -def get_typedict(cls): - pass - -class Entry(ExtRegistryEntry): - _about_ = get_typedict - s_result_annotation = annmodel.SomeObject() - - def specialize_call(self, hop): - v_type, = hop.inputargs(*hop.args_r) - assert hop.args_r[0] == robject.pyobj_repr, ( - 'get_typedict works for Python types only') - v_res = hop.llops.gencapicall('postsetup_get_typedict', [v_type], - resulttype=robject.pyobj_repr) - return v_res - -def __init__(mod): - import types - import __builtin__ as bltn - hasattr = bltn.hasattr - isinstance = bltn.isinstance - - funcs = bltn.dict() # no hashing function for PyObject - idx = 0 - while 1: - name = get_methodname(idx) - if not name: - break - func = getattr(mod, name) - funcs[func] = idx - idx += 1 - - for name in mod.__all__: - obj = getattr(mod, name) - if isinstance(obj, type) and hasattr(obj, '__self__'): - cls = obj - dic = get_typedict(cls) - for name, value in dic.items(): - if isinstance(value, types.BuiltinFunctionType) and value in funcs: - idx = funcs[value] - meth = build_method(idx, cls) - dic[name] = meth - elif isinstance(value, property): - stuff = [value.fget, value.fset, value.fdel, value.__doc__] - for i, fn in enumerate(stuff): - if fn in funcs: - idx = funcs[fn] - stuff[i] = build_method(idx, cls) - if not stuff[-1]: - # use fget's doc if we don't ahve one - stuff[-1] = getattr(stuff[0], '__doc__', None) - dic[name] = property(*stuff) - # creating an object, wrapping, unwrapping, call function, check whether __del__ is called def test_wrap_call_dtor(): - f = getcompiled(democlass_helper, use_boehm=not True, exports=[DemoSubclass]) + f = get_compiled(democlass_helper, use_boehm=not True, exports=[DemoSubclass]) ret = f(2, 3) if P: print ret assert ret[0] == 1 @@ -420,6 +144,19 @@ assert res == DemoClass(2, 3).demo() assert (obj + obj).demo() == 10 +def test_extcompiler(): + compiler = ExtCompiler(t) + compiler.export(DemoClass) + compiler.export(DemoSubclass) + compiler.export(DemoNotAnnotated) + compiler.export(42, name='zweiundvierzig') + m = compiler.build('testmodule') + obj = m.DemoClass(2, 3) + res = obj.demo() + assert res == DemoClass(2, 3).demo() + assert (obj + obj).demo() == 10 + assert hasattr(m, '__init__') + if __name__=='__main__': test_expose_classes() - + \ No newline at end of file Added: pypy/dist/pypy/translator/tool/raymond.py ============================================================================== --- (empty file) +++ pypy/dist/pypy/translator/tool/raymond.py Tue May 23 21:57:36 2006 @@ -0,0 +1,313 @@ +from pypy.translator.translator import TranslationContext +from pypy import conftest +from py.test import raises +from pypy.rpython.extregistry import ExtRegistryEntry +from pypy.annotation import model as annmodel +from pypy.rpython.lltypesystem import lltype +from pypy.rpython import robject, rclass, rint +from pypy.translator.tool.cbuild import enable_fast_compilation +from pypy.interpreter.baseobjspace import ObjSpace + +import sys, types + +P = False # debug printing + +SPECIAL_METHODS = {} + +def setup_special_methods(): + for name, op, arity, funcs in ObjSpace.MethodTable: + for fname in funcs: + if fname.startswith('__'): + ann = [None] * arity # replaced by class + if 'attr' in fname: + ann[1] = str + elif 'item' in fname: + ann[1] = int + elif 'pow' in fname: + ann[1] = int + elif 'shift' in fname: + ann[1] = int + if arity == 3 and '_set' in fname: + ann[-1] = object + SPECIAL_METHODS[fname] = ann +setup_special_methods() + +def get_annotation(func, pre=[]): + argstypelist = pre[:] + if hasattr(func, '_initialannotation_'): + for spec in func._initialannotation_: + argstypelist.append(spec) + if len(argstypelist) == 1: + argstypelist = guess_methannotation(func, argstypelist[0]) + missing = [object] * (func.func_code.co_argcount - len(argstypelist)) + return missing + argstypelist + +def guess_methannotation(func, cls): + ret = [cls] + if func.__name__ in SPECIAL_METHODS: + pattern = SPECIAL_METHODS[func.__name__] + ret = [thetype or cls for thetype in pattern] + return ret + +def get_compiled_module(func, view=conftest.option.view, inline_threshold=1, + use_boehm=False, exports=None): + from pypy.translator.translator import TranslationContext + from pypy.translator.backendopt.all import backend_optimizations + + from pypy.translator.c import gc + from pypy.translator.c.genc import CExtModuleBuilder + + global _t # allow us to view later + _t = t = TranslationContext(do_imports_immediately=False) + ann = t.buildannotator() + rtyper = t.buildrtyper() + bk = rtyper.annotator.bookkeeper + if not exports: + exports = [] + + ann.build_types(func, get_annotation(func)) + + pyobj_options = {} + + for obj in exports: + if isinstance(obj, tuple): + _, obj = obj + if isinstance(obj, type): + cls = obj + clsdef = bk.getuniqueclassdef(cls) + rtyper.add_wrapper(clsdef) + for obj in cls.__dict__.values(): + if isinstance(obj, types.FunctionType): + if not ann.bookkeeper.getdesc(obj).querycallfamily(): + # not annotated, so enforce it + ann.build_types(obj, get_annotation(obj, [cls]), complete_now=False) + elif isinstance(obj, property): + for obj in obj.fget, obj.fset, obj.fdel: + if obj and not ann.bookkeeper.getdesc(obj).querycallfamily(): + ann.build_types(obj, get_annotation(obj, [cls]), complete_now=False) + elif isinstance(obj, types.FunctionType): + if not ann.bookkeeper.getdesc(obj).querycallfamily(): + # not annotated, so enforce it + ann.build_types(obj, get_annotation(obj), complete_now=False) + if obj.__name__ == '__init__': + pyobj_options['use_true_methods'] = True + + all = [] + for obj in exports: + if isinstance(obj, tuple): + name, obj = obj + else: + name = obj.__name__ + if name != '__init__': + all.append(name) + + exports = exports + [('__all__', all)] + + ann.build_types(func, get_annotation(func)) + if view: + t.viewcg() + rtyper.specialize() + if view: + t.viewcg() + t.checkgraphs() + + gcpolicy = None + if use_boehm: + gcpolicy = gc.BoehmGcPolicy + + backend_optimizations(t, inline_threshold=inline_threshold) + if view: + t.viewcg() + + cbuilder = CExtModuleBuilder(t, func, gcpolicy=gcpolicy) + # explicit build of database + db = cbuilder.build_database(exports=exports, pyobj_options=pyobj_options) + cbuilder.generate_source(db) + if view: + t.viewcg() + cbuilder.compile() + + return cbuilder.import_module() + +def get_compiled(func, *args, **kwds): + module = get_compiled_module(func, *args, **kwds) + return getattr(module, func.__name__) + +# _______________________________________________- +# stubs for special annotation/rtyping + +## these are not used for production right now. + +def wrap(thing): + return thing # untranslated case + +def unwrap(pyobj, typ): + assert isinstance(pyobj, typ) + return pyobj # untranslated case +unwrap._annspecialcase_ = 'specialize:arg(1)' + + +# XXX +# wrapping/unwrapping should be annotatable. +# Idea: create tunnel objects which share +# annotation across SomeObjectness, sharing a key! + +class Entry(ExtRegistryEntry): + _about_ = unwrap + + def compute_result_annotation(self, s_wrapped, s_spec): + # this will go away, much better way found! + assert hasattr(s_spec, 'descriptions'), 'need a class in unwrap 2nd arg' + descs = s_spec.descriptions + assert len(descs) == 1, 'missing specialisation, classdesc not unique!' + for desc in descs.keys(): + classdef = desc.getuniqueclassdef() + return annmodel.SomeInstance(classdef) + + def specialize_call(self, hop): + v_obj = hop.inputarg(hop.args_r[0], 0) + return hop.llops.convertvar(v_obj, hop.args_r[0], hop.r_result) + + +class Entry(ExtRegistryEntry): + _about_ = wrap + + s_result_annotation = annmodel.SomeObject() + + def specialize_call(self, hop): + assert len(hop.args_r) == 1, 'wrap() takes exactly one argument' + v_obj, = hop.inputargs(*hop.args_r) + return hop.llops.convertvar(v_obj, hop.args_r[0], robject.pyobj_repr) + +# _______________________________________________ +# creating our own setup function for the module + +# this class *can* be used for faster access. +# the compiler anyway chews quite a bit on it... +class BuiltinHelper(object): + # the following would be much easier if we had + # loop unrolling right inside the flowing process + src = [] + src.append('def __init__(self):') + src.append(' import __builtin__ as b') + import __builtin__ + for name in dir(__builtin__): + obj = getattr(__builtin__, name) + if callable(obj) and hasattr(obj, '__name__'): + src.append(' self.%s = b.%s' % (name, obj.__name__)) + src = '\n'.join(src) + #print src + exec src + del __builtin__, name, obj, src + + +def get_methodname(funcidx): + pass + +class Entry(ExtRegistryEntry): + _about_ = get_methodname + s_result_annotation = annmodel.SomeObject() + + def specialize_call(self, hop): + v_idx, = hop.inputargs(*hop.args_r) + if hop.args_r[0] <> rint.signed_repr: + v_idx = hop.llops.convertvar(v_idx, + r_from=hop.args_r[0], + r_to=rint.signed_repr) + v_res = hop.llops.gencapicall('postsetup_get_methodname', [v_idx], + resulttype=robject.pyobj_repr) + return v_res + +def build_method(funcidx): + pass + +class Entry(ExtRegistryEntry): + _about_ = build_method + s_result_annotation = annmodel.SomeObject() + + def specialize_call(self, hop): + v_idx, v_type = hop.inputargs(*hop.args_r) + if hop.args_r[0] <> rint.signed_repr: + v_idx = hop.llops.convertvar(v_idx, + r_from=hop.args_r[0], + r_to=rint.signed_repr) + assert hop.args_r[1] == robject.pyobj_repr, ( + 'build_method works for Python types only') + v_res = hop.llops.gencapicall('postsetup_build_method', [v_idx, v_type], + resulttype=robject.pyobj_repr) + return v_res + +def get_typedict(cls): + pass + +class Entry(ExtRegistryEntry): + _about_ = get_typedict + s_result_annotation = annmodel.SomeObject() + + def specialize_call(self, hop): + v_type, = hop.inputargs(*hop.args_r) + assert hop.args_r[0] == robject.pyobj_repr, ( + 'get_typedict works for Python types only') + v_res = hop.llops.gencapicall('postsetup_get_typedict', [v_type], + resulttype=robject.pyobj_repr) + return v_res + +def __init__(mod): + """ + this module init function walks through all exported classes + and tries to build real methods from the functions. + properties are re-created, too. + """ + import types + import __builtin__ as bltn + bltn = BuiltinHelper() + hasattr = bltn.hasattr + isinstance = bltn.isinstance + + funcs = bltn.dict() # no hashing function for PyObject + idx = 0 + while 1: + name = get_methodname(idx) + if not name: + break + func = getattr(mod, name) + funcs[func] = idx + idx += 1 + + for name in mod.__all__: + obj = getattr(mod, name) + if isinstance(obj, type) and hasattr(obj, '__self__'): + cls = obj + dic = get_typedict(cls) + for name, value in dic.items(): + if isinstance(value, types.BuiltinFunctionType) and value in funcs: + idx = funcs[value] + meth = build_method(idx, cls) + dic[name] = meth + elif isinstance(value, property): + stuff = [value.fget, value.fset, value.fdel, value.__doc__] + for i, fn in enumerate(stuff): + if fn in funcs: + idx = funcs[fn] + stuff[i] = build_method(idx, cls) + if not stuff[-1]: + # use fget's doc if we don't ahve one + stuff[-1] = getattr(stuff[0], '__doc__', None) + dic[name] = property(*stuff) + +class ExtCompiler(object): + def __init__(self, startupfunc, use_true_methods=True): + self.startupfunc = startupfunc + self.exports = {} + if use_true_methods: + self.export(__init__) + + def export(self, obj, name=None): + if name: + self.exports[name] = (name, obj) + else: + self.exports[obj.__name__] = obj + + def build(self, modname): + mod = get_compiled_module(self.startupfunc, exports=self.exports.values()) + return mod From antocuni at codespeak.net Wed May 24 10:22:12 2006 From: antocuni at codespeak.net (antocuni at codespeak.net) Date: Wed, 24 May 2006 10:22:12 +0200 (CEST) Subject: [pypy-svn] r27631 - pypy/dist/pypy/rpython/test Message-ID: <20060524082212.4363910077@code0.codespeak.net> Author: antocuni Date: Wed May 24 10:22:02 2006 New Revision: 27631 Modified: pypy/dist/pypy/rpython/test/test_rlist.py Log: Don't skip a test that now passes. 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 Wed May 24 10:22:02 2006 @@ -735,7 +735,6 @@ def test_list_str(self): - self._skip_oo('int to string') def fn(): return str([1,2,3]) @@ -803,7 +802,7 @@ def test_inst_list(self): - self._skip_oo('strings') + self._skip_oo('list to string') def fn(): l = [None] l[0] = Foo() @@ -818,7 +817,7 @@ x = l2.pop() return str(x)+";"+str(l) res = self.interpret(fn, []) - assert ''.join(res.chars) == ';[, , , , ]' + assert self.ll_to_string(res) == ';[, , , , ]' def fn(): l = [None] * 2 @@ -832,7 +831,7 @@ i += 1 return str(l) res = self.interpret(fn, []) - assert ''.join(res.chars) == '[, , , , ]' + assert self.ll_to_string(res) == '[, , , , ]' def test_list_slice_minusone(self): def fn(i): From antocuni at codespeak.net Wed May 24 10:27:44 2006 From: antocuni at codespeak.net (antocuni at codespeak.net) Date: Wed, 24 May 2006 10:27:44 +0200 (CEST) Subject: [pypy-svn] r27632 - pypy/dist/pypy/rpython/test Message-ID: <20060524082744.894971006F@code0.codespeak.net> Author: antocuni Date: Wed May 24 10:27:35 2006 New Revision: 27632 Modified: pypy/dist/pypy/rpython/test/test_rlist.py Log: Don't skip yet another test. 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 Wed May 24 10:27:35 2006 @@ -802,7 +802,6 @@ def test_inst_list(self): - self._skip_oo('list to string') def fn(): l = [None] l[0] = Foo() @@ -816,8 +815,9 @@ x = l.pop() x = l2.pop() return str(x)+";"+str(l) - res = self.interpret(fn, []) - assert self.ll_to_string(res) == ';[, , , , ]' + res = self.ll_to_string(self.interpret(fn, [])) + res = res.replace('pypy.rpython.test.test_rlist.', '') + assert res == ';[, , , , ]' def fn(): l = [None] * 2 @@ -830,8 +830,9 @@ l[i] = x i += 1 return str(l) - res = self.interpret(fn, []) - assert self.ll_to_string(res) == '[, , , , ]' + res = self.ll_to_string(self.interpret(fn, [])) + res = res.replace('pypy.rpython.test.test_rlist.', '') + assert res == '[, , , , ]' def test_list_slice_minusone(self): def fn(i): From arigo at codespeak.net Wed May 24 10:33:25 2006 From: arigo at codespeak.net (arigo at codespeak.net) Date: Wed, 24 May 2006 10:33:25 +0200 (CEST) Subject: [pypy-svn] r27633 - pypy/dist/pypy/annotation Message-ID: <20060524083325.812BF10071@code0.codespeak.net> Author: arigo Date: Wed May 24 10:33:24 2006 New Revision: 27633 Modified: pypy/dist/pypy/annotation/__init__.py Log: Workaround for a circular import problem. The import order is important. Modified: pypy/dist/pypy/annotation/__init__.py ============================================================================== --- pypy/dist/pypy/annotation/__init__.py (original) +++ pypy/dist/pypy/annotation/__init__.py Wed May 24 10:33:24 2006 @@ -1 +1,4 @@ -# +# workaround for a circular imports problem +# e.g. if you import pypy.annotation.listdef first + +import pypy.annotation.model From antocuni at codespeak.net Wed May 24 11:00:36 2006 From: antocuni at codespeak.net (antocuni at codespeak.net) Date: Wed, 24 May 2006 11:00:36 +0200 (CEST) Subject: [pypy-svn] r27634 - in pypy/dist/pypy/rpython/ootypesystem: . test Message-ID: <20060524090036.7D1EE1006D@code0.codespeak.net> Author: antocuni Date: Wed May 24 11:00:25 2006 New Revision: 27634 Modified: pypy/dist/pypy/rpython/ootypesystem/ooregistry.py pypy/dist/pypy/rpython/ootypesystem/test/test_oostring.py Log: Added support for using string constant obtained from string_repr.convert_const in ootypesysyem ll helpers. Modified: pypy/dist/pypy/rpython/ootypesystem/ooregistry.py ============================================================================== --- pypy/dist/pypy/rpython/ootypesystem/ooregistry.py (original) +++ pypy/dist/pypy/rpython/ootypesystem/ooregistry.py Wed May 24 11:00:25 2006 @@ -23,6 +23,13 @@ return hop.genop('oostring', hop.args_v, resulttype = ootype.String) +class Entry_ootype_string(ExtRegistryEntry): + _type_ = ootype._string + + def compute_annotation(self): + return annmodel.SomeOOInstance(ootype=ootype.String) + + class Entry_ooparse_int(ExtRegistryEntry): _about_ = ootype.ooparse_int Modified: pypy/dist/pypy/rpython/ootypesystem/test/test_oostring.py ============================================================================== --- pypy/dist/pypy/rpython/ootypesystem/test/test_oostring.py (original) +++ pypy/dist/pypy/rpython/ootypesystem/test/test_oostring.py Wed May 24 11:00:25 2006 @@ -1,4 +1,5 @@ from pypy.rpython.ootypesystem import ootype +from pypy.rpython.ootypesystem.rstr import string_repr from pypy.rpython.test.test_llinterp import interpret def test_constant_string(): @@ -13,3 +14,15 @@ b.ll_append(ootype.make_string('bcd')) res = b.ll_build() assert res._str == 'abcd' + +def test_constant_repr(): + myconst = string_repr.convert_const('foo') + assert isinstance(myconst, ootype._string) + + def f(): + buf = ootype.new(ootype.StringBuilder) + buf.ll_append(myconst) + return buf.ll_build() + + res = interpret(f, [], type_system='ootype') + assert res._str == 'foo' From arigo at codespeak.net Wed May 24 13:16:14 2006 From: arigo at codespeak.net (arigo at codespeak.net) Date: Wed, 24 May 2006 13:16:14 +0200 (CEST) Subject: [pypy-svn] r27641 - pypy/extradoc/talk/dls2006 Message-ID: <20060524111614.38BC310068@code0.codespeak.net> Author: arigo Date: Wed May 24 13:16:13 2006 New Revision: 27641 Added: pypy/extradoc/talk/dls2006/draft.txt (contents, props changed) Modified: pypy/extradoc/talk/dls2006/ (props changed) pypy/extradoc/talk/dls2006/outline.txt Log: Started working on a draft. Added: pypy/extradoc/talk/dls2006/draft.txt ============================================================================== --- (empty file) +++ pypy/extradoc/talk/dls2006/draft.txt Wed May 24 13:16:13 2006 @@ -0,0 +1,158 @@ +************************************************************ + Still Missing a Cool Title +************************************************************ + +:Abstract: + + The PyPy project seeks to prove both on a research and on a + practical level the feasability of writing a virtual machine (VM) + for a dynamic language in a dynamic language - in this case, Python. + The aim is to translate (i.e. compile) the VM to arbitrary target + environments, ranging in level from C/Posix to Smalltalk/Squeak via + Java and CLI/.NET, while still being of reasonable efficiency within + that environment. + + A key tool to achieve this goal is the systematic reuse of the + (unmodified, dynamically typed) Python language as a system + programming language at various levels of our architecture and + translation process. For each level, we design a corresponding type + system and apply a generic type inference engine - for example, the + garbage collector (GC) is written in a style that manipulates + simulated pointer and address objects, and when translated to C + these operations become C-level pointer and address instructions. + +.. sectnum:: + + +.. _`section 1`: + +============================================================ + Introduction +============================================================ + + +Despite the constant trend in the programming world towards portability +and reusability, there are some areas in which it is still notoriously +difficult to write flexible, portable, and reasonably efficient +programs. Virtual machines (VM) is one such area. Building +implementations of general programming languages, in particular highly +dynamic ones, is typically a long-winded effort and produces a result +that is quite tailored to a specific platform. For this and other +reasons, standard platforms emerge; nowadays, a language implementor +could cover most general platforms in use by writing three versions of +his VM: for C/Posix, for Java, and for CLI/.NET. This is, at least, the +current situation of the Python programming language, where independent +volunteers developped and are now maintaining Java and .NET versions of +Python, which follow the evolution of the "official" C version +(CPython). + +However, we believe that platform standardization does not have to be a +necessary component of this equation. We are basically using the +standard "metaprogramming" argument: if one could write the VM in a +very-high-level language, then the VM itself could be automatically +*translated* to any lower-level platform. Moreover by writing the VM in +such a language we would gain in flexibility and expressivity. + +PyPy achieves this goal without giving up on the efficiency of the +compiled VMs. The key factors enabling this result are not to be found +in recent advances in any particular research area - we are not using +any sophisticated GC, any constraint-based type inference, any advanced +mega-programming concepts. Instead, we are following a novel overall +architecture: it is split in many levels of stepwise translation from +the high-level source of the VM to the final target platform. Similar +platforms can reuse many of these steps, while for very different +platforms we have the option to perform very different translation +steps. Each step reuses a common type inference component, but with a +different type system. + +Experiments also suggest a more mundane reason why such an approach is +only practical today: a typical translation takes about an hour on a +modern PC and consumes close to 1GB of RAM. + +We shortly describe the architecture of PyPy in `section 2`_. In +`section 3`_ we describe our approach of varying the type systems at +various levels of the translation. `Section 4`_ gives an overview of +the type inferencer we developped. We present experimental results in +`section 5`_ and future work directions in `section 6`_. In `section 7`_ +we compare with related work, and finally we conclude in `section 8`_. + + +.. _`section 2`: + +============================================================ + Architecture +============================================================ + + +XXX it contains on +the one hand an implementation of the Python programming language, +mostly complete and compliant with the current version of the language, +Python 2.4. Our current efforts are focused on the second part, which +is a translation toolsuite whose goal is, roughly speaking, to compile +various subsets of Python to various environment. + + + +.. _`section 3`: + +============================================================ + System programming with Python +============================================================ + + +XXX + + + +.. _`section 4`: + +============================================================ + Type inference +============================================================ + + +XXX + + + +.. _`section 5`: + +============================================================ + Experimental results +============================================================ + + +XXX + + + +.. _`section 6`: + +============================================================ + Future work +============================================================ + + +XXX + + + +.. _`section 7`: + +============================================================ + Related work +============================================================ + + +XXX + + + +.. _`section 8`: + +============================================================ + Conclusion +============================================================ + + +XXX Modified: pypy/extradoc/talk/dls2006/outline.txt ============================================================================== --- pypy/extradoc/talk/dls2006/outline.txt (original) +++ pypy/extradoc/talk/dls2006/outline.txt Wed May 24 13:16:13 2006 @@ -6,9 +6,14 @@ Introduction ============ -High-level architecture, VM portability+flexibility goals with comparisons +VM portability+flexibility goals with comparisons (rigidity, less expressiveness of implementation languages) +Architecture +============ + +High-level architecture, shortly + System programming with Python ============================== @@ -27,6 +32,11 @@ and to reuse with different type systems: RPython, ll, oo, rctypes, BTA (binding-time analysis for the JIT)... easy custom specializations +Experimental results +==================== + +a few numbers + Future work =========== From antocuni at codespeak.net Wed May 24 13:22:52 2006 From: antocuni at codespeak.net (antocuni at codespeak.net) Date: Wed, 24 May 2006 13:22:52 +0200 (CEST) Subject: [pypy-svn] r27644 - in pypy/dist/pypy/rpython: ootypesystem test Message-ID: <20060524112252.5B3021006D@code0.codespeak.net> Author: antocuni Date: Wed May 24 13:22:36 2006 New Revision: 27644 Modified: pypy/dist/pypy/rpython/ootypesystem/ootype.py pypy/dist/pypy/rpython/ootypesystem/rdict.py pypy/dist/pypy/rpython/test/test_rdict.py Log: Some refactoring of test_rdict, and some little bugs fixed. Modified: pypy/dist/pypy/rpython/ootypesystem/ootype.py ============================================================================== --- pypy/dist/pypy/rpython/ootypesystem/ootype.py (original) +++ pypy/dist/pypy/rpython/ootypesystem/ootype.py Wed May 24 13:22:36 2006 @@ -809,6 +809,12 @@ self._str = value self._TYPE = STRING + def __hash__(self): + return hash(self._str) + + def __cmp__(self, other): + return cmp(self._str, other._str) + def ll_stritem_nonneg(self, i): # NOT_RPYTHON assert i >= 0 @@ -987,7 +993,7 @@ return self._dict[key] def ll_set(self, key, value): - # NOT_RPYTHON + # NOT_RPYTHON assert typeOf(key) == self._TYPE._KEYTYPE assert typeOf(value) == self._TYPE._VALUETYPE self._dict[key] = value @@ -1076,6 +1082,13 @@ else: return 0 # for all null tuples + def __hash__(self): + key = tuple(self._items.keys()), tuple(self._items.values()) + return hash(key) + + def __eq__(self, other): + return self._items == other._items + class _null_record(_null_mixin(_record), _record): def __init__(self, RECORD): Modified: pypy/dist/pypy/rpython/ootypesystem/rdict.py ============================================================================== --- pypy/dist/pypy/rpython/ootypesystem/rdict.py (original) +++ pypy/dist/pypy/rpython/ootypesystem/rdict.py Wed May 24 13:22:36 2006 @@ -137,7 +137,7 @@ def convert_const(self, dictobj): if dictobj is None: - return lltype.nullptr(self.DICT) + return self.DICT._defl() if not isinstance(dictobj, dict): raise TyperError("expected a dict: %r" % (dictobj,)) try: @@ -180,7 +180,7 @@ ## hop.exception_is_here() ## else: ## hop.exception_cannot_occur() - hop.exception_is_here() +## hop.exception_is_here() return r_dict.send_message(hop, 'll_set', can_raise=True) def rtype_contains((r_dict, r_key), hop): 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 Wed May 24 13:22:36 2006 @@ -3,461 +3,11 @@ from pypy.rpython.test.test_llinterp import interpret, interpret_raises from pypy.rpython import rint from pypy.rpython.lltypesystem import rdict, rstr +from pypy.rpython.test.tool import BaseRtypingTest, LLRtypeMixin, OORtypeMixin import py py.log.setconsumer("rtyper", py.log.STDOUT) -class BaseTestDictRtyping: - def interpret(self, fn, args): - return interpret(fn, args, type_system=self.ts) - - def interpret_raises(self, exc, fn, args): - return interpret_raises(exc, fn, args, type_system=self.ts) - - -# XXX: most tests doesn't works because ootypesystem doesn't support strings, yet -def test_dict_creation(): - def createdict(i): - d = {'hello' : i} - return d['hello'] - - 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 - -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_but_not_with_char_keys(): - def func(i): - d = {'h': i} - try: - return d['hello'] - 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 - -def test_dict_clear(): - def func(i): - d = {'abc': i} - d['def'] = i+1 - d.clear() - d['ghi'] = i+2 - return ('abc' not in d and 'def' not in d - and d['ghi'] == i+2 and len(d) == 1) - res = interpret(func, [7]) - assert res == True - -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.LLHelpers.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] - - char_by_hash = {} - base = rdict.DICT_INITSIZE - 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), ord(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), ord(y)]) - for i in range(len(res.entries)): - assert not (res.entries[i].everused() and not res.entries[i].valid()) - - 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 - - if rdict.DICT_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.DICT_INITSIZE)]) - count_frees = 0 - for i in range(len(res.entries)): - if not res.entries[i].everused(): - count_frees += 1 - assert count_frees >= 3 - -def test_dict_resize(): - def func(want_empty): - d = {} - for i in range(rdict.DICT_INITSIZE): - d[chr(ord('a') + i)] = i - if want_empty: - for i in range(rdict.DICT_INITSIZE): - del d[chr(ord('a') + i)] - return d - res = interpret(func, [0]) - assert len(res.entries) > rdict.DICT_INITSIZE - res = interpret(func, [1]) - assert len(res.entries) == rdict.DICT_INITSIZE - -def test_dict_valid_resize(): - # see if we find our keys after resize - def func(): - d = {} - # fill it up - for i in range(10): - d[str(i)] = 0 - # delete again - for i in range(10): - del d[str(i)] - res = 0 - # if it does not crash, we are fine. It crashes if you forget the hash field. - interpret(func, []) - -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 - -def test_dict_itermethods(): - def func(): - d = {} - d['hello'] = 6 - d['world'] = 7 - k1 = k2 = k3 = 1 - for key in d.iterkeys(): - k1 = k1 * d[key] - for value in d.itervalues(): - k2 = k2 * value - for key, value in d.iteritems(): - assert d[key] == value - k3 = k3 * value - return k1 + k2 + k3 - res = interpret(func, []) - assert res == 42 + 42 + 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 - -def test_dict_get(): - def func(): - 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_setdefault(): - def f(): - d = {} - d.setdefault('a', 2) - return d['a'] - res = interpret(f, ()) - assert res == 2 - - def f(): - d = {} - d.setdefault('a', 2) - x = d.setdefault('a', -3) - return x - res = interpret(f, ()) - assert res == 2 - -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, ())#, view=True) - assert res == 14 - -def test_dict_inst_keys(): - class Empty: - pass - class A(Empty): - pass - def func(): - dic0 = {Empty(): 2} - dic = {A(): 1, A(): 2} - keys = dic.keys() - return (isinstance(keys[1], A))*2+(isinstance(keys[0],A)) - res = interpret(func, []) - assert res == 3 - -def test_dict_inst_iterkeys(): - class Empty: - pass - class A(Empty): - pass - def func(): - dic0 = {Empty(): 2} - dic = {A(): 1, A(): 2} - a = 0 - for k in dic.iterkeys(): - a += isinstance(k, A) - return a - res = interpret(func, []) - assert res == 2 - -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_inst_values(): - class A: - pass - def func(): - dic = {1: A(), 2: A()} - vals = dic.values() - return (isinstance(vals[1], A))*2+(isinstance(vals[0],A)) - res = interpret(func, []) - assert res == 3 - -def test_dict_inst_itervalues(): - class A: - pass - def func(): - dic = {1: A(), 2: A()} - a = 0 - for v in dic.itervalues(): - a += isinstance(v, A) - return a - res = interpret(func, []) - assert res == 2 - -def test_dict_inst_items(): - class Empty: - pass - class A: - pass - class B(Empty): - pass - def func(): - dic0 = {Empty(): 2} - dic = {B(): A(), B(): A()} - items = dic.items() - b = 0 - a = 0 - for k, v in items: - b += isinstance(k, B) - a += isinstance(v, A) - return 3*b+a - res = interpret(func, []) - assert res == 8 - -def test_dict_inst_iteritems(): - class Empty: - pass - class A: - pass - class B(Empty): - pass - def func(): - dic0 = {Empty(): 2} - dic = {B(): A(), B(): A()} - b = 0 - a = 0 - for k, v in dic.iteritems(): - b += isinstance(k, B) - a += isinstance(v, A) - return 3*b+a - res = interpret(func, []) - assert res == 8 - -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 - -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 - -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 - -def dict_or_none(): - class A: - pass - def negate(d): - return not d - def func(n): - a = A() - a.d = None - if n > 0: - a.d = {str(n): 1, "42": 2} - del a.d["42"] - return negate(a.d) - res = interpret(func, [10]) - assert res is False - res = interpret(func, [0]) - assert res is True - res = interpret(func, [42]) - assert res is True - -def test_int_dict(): - def func(a, b): - dic = {12: 34} - dic[a] = 1000 - return dic.get(b, -123) - res = interpret(func, [12, 12]) - assert res == 1000 - res = interpret(func, [12, 13]) - assert res == -123 - res = interpret(func, [524, 12]) - assert res == 34 - res = interpret(func, [524, 524]) - assert res == 1000 - res = interpret(func, [524, 1036]) - assert res == -123 - -# ____________________________________________________________ - def not_really_random(): """A random-ish generator, which also generates nice patterns from time to time. Could be useful to detect problems associated with specific usage patterns.""" @@ -470,283 +20,75 @@ assert 0 <= x < 4 yield x -def test_stress(): - from pypy.annotation.dictdef import DictKey, DictValue - from pypy.annotation import model as annmodel - dictrepr = rdict.DictRepr(None, rint.signed_repr, rint.signed_repr, - DictKey(None, annmodel.SomeInteger()), - DictValue(None, annmodel.SomeInteger())) - dictrepr.setup() - l_dict = rdict.ll_newdict(dictrepr.DICT) - referencetable = [None] * 400 - referencelength = 0 - value = 0 - - def complete_check(): - for n, refvalue in zip(range(len(referencetable)), referencetable): - try: - gotvalue = rdict.ll_dict_getitem(l_dict, n) - except KeyError: - assert refvalue is None - else: - assert gotvalue == refvalue - - for x in not_really_random(): - n = int(x*100.0) # 0 <= x < 400 - op = repr(x)[-1] - if op <= '2' and referencetable[n] is not None: - rdict.ll_dict_delitem(l_dict, n) - referencetable[n] = None - referencelength -= 1 - elif op <= '6': - rdict.ll_dict_setitem(l_dict, n, value) - if referencetable[n] is None: - referencelength += 1 - referencetable[n] = value - value += 1 - else: - try: - gotvalue = rdict.ll_dict_getitem(l_dict, n) - except KeyError: - assert referencetable[n] is None - else: - assert gotvalue == referencetable[n] - if 1.38 <= x <= 1.39: - complete_check() - print 'current dict length:', referencelength - assert l_dict.num_items == referencelength - complete_check() - -# ____________________________________________________________ - -def test_opt_nullkeymarker(): - def f(): - d = {"hello": None} - d["world"] = None - return "hello" in d, d - res = interpret(f, []) - assert res.item0 == True - DICT = lltype.typeOf(res.item1).TO - assert not hasattr(DICT.entries.TO.OF, 'f_everused')# non-None string keys - assert not hasattr(DICT.entries.TO.OF, 'f_valid') # strings have a dummy - -def test_opt_nullvaluemarker(): - def f(n): - d = {-5: "abcd"} - d[123] = "def" - return len(d[n]), d - res = interpret(f, [-5]) - assert res.item0 == 4 - DICT = lltype.typeOf(res.item1).TO - assert not hasattr(DICT.entries.TO.OF, 'f_everused')# non-None str values - assert not hasattr(DICT.entries.TO.OF, 'f_valid') # strs have a dummy - -def test_opt_nonullmarker(): - class A: - pass - def f(n): - if n > 5: - a = A() - else: - a = None - d = {a: -5441} - d[A()] = n+9872 - return d[a], d - res = interpret(f, [-5]) - assert res.item0 == -5441 - DICT = lltype.typeOf(res.item1).TO - assert hasattr(DICT.entries.TO.OF, 'f_everused') # can-be-None A instances - assert not hasattr(DICT.entries.TO.OF, 'f_valid')# with a dummy A instance - - res = interpret(f, [6]) - assert res.item0 == -5441 - -def test_opt_nonnegint_dummy(): - def f(n): - d = {n: 12} - d[-87] = 24 - del d[n] - return len(d.copy()), d[-87], d - res = interpret(f, [5]) - assert res.item0 == 1 - assert res.item1 == 24 - DICT = lltype.typeOf(res.item2).TO - assert hasattr(DICT.entries.TO.OF, 'f_everused') # all ints can be zero - assert not hasattr(DICT.entries.TO.OF, 'f_valid')# nonneg int: dummy -1 - -def test_opt_no_dummy(): - def f(n): - d = {n: 12} - d[-87] = -24 - del d[n] - return len(d.copy()), d[-87], d - res = interpret(f, [5]) - assert res.item0 == 1 - assert res.item1 == -24 - DICT = lltype.typeOf(res.item2).TO - assert hasattr(DICT.entries.TO.OF, 'f_everused') # all ints can be zero - assert hasattr(DICT.entries.TO.OF, 'f_valid') # no dummy available - -def test_opt_multiple_identical_dicts(): - def f(n): - s = "x" * n - d1 = {s: 12} - d2 = {s: 24} - d3 = {s: 36} - d1["a"] = d2[s] # 24 - d3[s] += d1["a"] # 60 - d2["bc"] = d3[s] # 60 - return d2["bc"], d1, d2, d3 - res = interpret(f, [5]) - assert res.item0 == 60 - # all three dicts should use the same low-level type - assert lltype.typeOf(res.item1) == lltype.typeOf(res.item2) - assert lltype.typeOf(res.item1) == lltype.typeOf(res.item3) - -# ____________________________________________________________ - -def test_id_instances_keys(): - class A: - pass - class B(A): - pass - def f(): - a = A() - b = B() - d = {} - d[b] = 7 - d[a] = 3 - return len(d) + d[a] + d[b] - res = interpret(f, []) - assert res == 12 - -def test_captured_get(): - get = {1:2}.get - def f(): - return get(1, 3)+get(2, 4) - res = interpret(f, []) - assert res == 6 - - def g(h): - return h(1, 3) - def f(): - return g(get) - - res = interpret(f, []) - assert res == 2 - -def test_specific_obscure_bug(): - class A: pass - class B: pass # unrelated kinds of instances - def f(): - lst = [A()] - res1 = A() in lst - d2 = {B(): None, B(): None} - return res1+len(d2) - res = interpret(f, []) - assert res == 2 - - -def test_type_erase(): - class A(object): - pass - class B(object): - pass - - def f(): - return {A(): B()}, {B(): A()} - - t = TranslationContext() - s = t.buildannotator().build_types(f, []) - rtyper = t.buildrtyper() - rtyper.specialize() - - s_AB_dic = s.items[0] - s_BA_dic = s.items[1] - - r_AB_dic = rtyper.getrepr(s_AB_dic) - r_BA_dic = rtyper.getrepr(s_AB_dic) - - assert r_AB_dic.lowleveltype == r_BA_dic.lowleveltype - -def test_tuple_dict(): - def f(i): - d = {} - d[(1, 2)] = 4 - d[(1, 3)] = 6 - return d[(1, i)] - - res = interpret(f, [2]) - assert res == f(2) - -def test_dict_of_dict(): - def f(n): - d = {} - d[5] = d - d[6] = {} - return len(d[n]) - - res = interpret(f, [5]) - assert res == 2 - res = interpret(f, [6]) - assert res == 0 - -def test_access_in_try(): - def f(d): - try: - return d[2] - except ZeroDivisionError: - return 42 - return -1 - def g(n): - d = {1: n, 2: 2*n} - return f(d) - res = interpret(g, [3]) - assert res == 6 - -def test_access_in_try_set(): - def f(d): - try: - d[2] = 77 - except ZeroDivisionError: - return 42 - return -1 - def g(n): - d = {1: n} - f(d) - return d[2] - res = interpret(g, [3]) - assert res == 77 +class BaseTestRdict(BaseRtypingTest): - -class TestLltypeRtyping(BaseTestDictRtyping): - ts = "lltype" - -class TestOotypeRtyping(BaseTestDictRtyping): - ts = "ootype" - - def ll_to_list(self, l): - return l._list[:] - - def ll_to_tuple(self, t, num): - lst = [getattr(t, 'item%d' % i) for i in range(num)] - return tuple(lst) - - # these tests are similar to those above, but they don't use strings def test_dict_creation(self): - def createdict(i): - d = {i: i+1} - return d[i] + def createdict(i): + d = {'hello' : i} + return d['hello'] + res = self.interpret(createdict, [42]) - assert res == 43 + assert res == 42 - def test_dict_getitem_setitem(self): + def test_dict_getitem_setitem(self): + def func(i): + d = {'hello' : i} + d['world'] = i + 1 + return d['hello'] * d['world'] + res = self.interpret(func, [6]) + assert res == 42 + + def test_dict_getitem_keyerror(self): + def func(i): + d = {'hello' : i} + try: + return d['world'] + except KeyError: + return 0 + res = self.interpret(func, [6]) + assert res == 0 + + def test_dict_del_simple(self): + def func(i): + d = {'hello' : i} + d['world'] = i + 1 + del d['hello'] + return len(d) + res = self.interpret(func, [6]) + assert res == 1 + + def test_dict_clear(self): def func(i): - d = {i: i+1} - d[i] = i+2 - return d[i] - res = self.interpret(func, [42]) + d = {'abc': i} + d['def'] = i+1 + d.clear() + d['ghi'] = i+2 + return ('abc' not in d and 'def' not in d + and d['ghi'] == i+2 and len(d) == 1) + res = self.interpret(func, [7]) + assert res == True + + def test_empty_strings(self): + def func(i): + d = {'' : i} + del d[''] + try: + d[''] + return 0 + except KeyError: + pass + return 1 + res = self.interpret(func, [6]) + assert res == 1 + + def func(i): + d = {'' : i} + del d[''] + d[''] = i + 1 + return len(d) + res = self.interpret(func, [6]) + assert res == 1 def test_dict_is_true(self): def func(i): @@ -768,115 +110,105 @@ assert self.interpret(func, [42, 0]) == False assert self.interpret(func, [42, 42]) == True - def test_delitem(self): - def func(x, y): - d = {x: x+1} - del d[y] - self.interpret(func, [42, 42]) # don't raise anything - self.interpret_raises(KeyError, func, [42, 0]) - def test_length(self): - def func(num): + def test_dict_iteration(self): + def func(i, j): d = {} - for i in range(num): - d[i] = i+1 - return len(d) - assert self.interpret(func, [0]) == 0 - assert self.interpret(func, [2]) == 2 + d['hello'] = i + d['world'] = j + k = 1 + for key in d: + k = k * d[key] + return k + res = self.interpret(func, [6, 7]) + assert res == 42 - def test_get(self): - def func(x, y): - d = {x: x+1} - return d.get(x, y) + d.get(x+1, y) - assert self.interpret(func, [42, 13]) == 56 - - def test_setdefault(self): - def func(x, y): + def test_dict_itermethods(self): + self._skip_oo('assert') + def func(): d = {} - d.setdefault(x, y) - return d[x] - assert self.interpret(func, [42, 13]) == 13 - - def test_keys(self): - def func(x, y): - d = {x: x+1, y: y+1} - return d.keys() - res = self.ll_to_list(self.interpret(func, [42, 13])) - assert res == [42, 13] or res == [13, 42] + d['hello'] = 6 + d['world'] = 7 + k1 = k2 = k3 = 1 + for key in d.iterkeys(): + k1 = k1 * d[key] + for value in d.itervalues(): + k2 = k2 * value + for key, value in d.iteritems(): + assert d[key] == value + k3 = k3 * value + return k1 + k2 + k3 + res = self.interpret(func, []) + assert res == 42 + 42 + 42 - def test_values(self): - def func(x, y): - d = {x: x+1, y: y+1} - return d.values() - res = self.ll_to_list(self.interpret(func, [42, 13])) - assert res == [43, 14] or res == [14, 43] - - def test_items(self): - def func(x, y): - d = {x: x+1, y: y+1} - return d.items() - res = self.ll_to_list(self.interpret(func, [42, 13])) - res = [self.ll_to_tuple(item, 2) for item in res] - assert res == [(42, 43), (13, 14)] or res == [(13, 14), (42, 43)] + def test_two_dicts_with_different_value_types(self): + def func(i): + d1 = {} + d1['hello'] = i + 1 + d2 = {} + d2['world'] = d1 + return d2['world']['hello'] + res = self.interpret(func, [5]) + assert res == 6 - def test_iteration(self): - def func(x, y): - d = {x: x+1, y: y+1} - tot = 0 - for key in d: - tot += key - return tot - assert self.interpret(func, [42, 13]) == 55 + def test_dict_get(self): + def func(): + dic = {} + x1 = dic.get('hi', 42) + dic['blah'] = 1 # XXX this triggers type determination + x2 = dic.get('blah', 2) + return x1 * 10 + x2 + res = self.interpret(func, ()) + assert res == 421 - def test_iterkeys(self): - def func(x, y): - d = {x: x+1, y: y+1} - tot = 0 - for key in d.iterkeys(): - tot += key - return tot - assert self.interpret(func, [42, 13]) == 55 + def test_dict_get_empty(self): + 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 = self.interpret(func, ()) + assert res == 422 - def test_itervalues(self): - def func(x, y): - d = {x: x+1, y: y+1} - tot = 0 - for value in d.itervalues(): - tot += value - return tot - assert self.interpret(func, [42, 13]) == 57 + def test_dict_setdefault(self): + def f(): + d = {} + d.setdefault('a', 2) + return d['a'] + res = self.interpret(f, ()) + assert res == 2 - def test_iteritems(self): - def func(x, y): - d = {x: x+1, y: y+1} - tot1 = 0 - tot2 = 0 - for key, value in d.iteritems(): - tot1 += key - tot2 += value - return tot1, tot2 - res = self.ll_to_tuple(self.interpret(func, [42, 13]), 2) - assert res == (55, 57) + def f(): + d = {} + d.setdefault('a', 2) + x = d.setdefault('a', -3) + return x + res = self.interpret(f, ()) + assert res == 2 - def test_copy(self): - def func(x, y): - d = {x: x+1, y: y+1} - d2 = d.copy() - d[x] = 0 - d[y] = 0 - tot1 = 0 - tot2 = 0 - for key, value in d2.iteritems(): - tot1 += key - tot2 += value - return tot1, tot2 - res = self.ll_to_tuple(self.interpret(func, [42, 13]), 2) - assert res == (55, 57) + def test_dict_copy(self): + self._skip_oo('mixing char and string') + 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 = self.interpret(func, ()) + assert res == 1 - def test_update(self): + def test_dict_update(self): + self._skip_oo('mixing char and string') def func(): - dic = {1:1000, 2:200} - d2 = {2:30, 3:4} + dic = {'ab':1000, 'b':200} + d2 = {'b':30, 'cb':4} dic.update(d2) ok = len(dic) == 3 sum = ok @@ -886,12 +218,540 @@ res = self.interpret(func, ()) assert res == 1035 - def test_clear(self): + def test_dict_keys(self): def func(): - dic = {1: 2, 3:4} - dic.clear() - return len(dic) - assert self.interpret(func, ()) == 0 + dic = {' 4':1000, ' 8':200} + keys = dic.keys() + return ord(keys[0][1]) + ord(keys[1][1]) - 2*ord('0') + len(keys) + res = self.interpret(func, ())#, view=True) + assert res == 14 + + def test_dict_inst_keys(self): + self._skip_oo('instances as keys') + class Empty: + pass + class A(Empty): + pass + def func(): + dic0 = {Empty(): 2} + dic = {A(): 1, A(): 2} + keys = dic.keys() + return (isinstance(keys[1], A))*2+(isinstance(keys[0],A)) + res = self.interpret(func, []) + assert res == 3 + + def test_dict_inst_iterkeys(self): + self._skip_oo('instances as keys') + class Empty: + pass + class A(Empty): + pass + def func(): + dic0 = {Empty(): 2} + dic = {A(): 1, A(): 2} + a = 0 + for k in dic.iterkeys(): + a += isinstance(k, A) + return a + res = self.interpret(func, []) + assert res == 2 + + def test_dict_values(self): + def func(): + dic = {' 4':1000, ' 8':200} + values = dic.values() + return values[0] + values[1] + len(values) + res = self.interpret(func, ()) + assert res == 1202 + + def test_dict_inst_values(self): + self._skip_oo('instances as values') + class A: + pass + def func(): + dic = {1: A(), 2: A()} + vals = dic.values() + return (isinstance(vals[1], A))*2+(isinstance(vals[0],A)) + res = self.interpret(func, []) + assert res == 3 + + def test_dict_inst_itervalues(self): + self._skip_oo('instances as values') + class A: + pass + def func(): + dic = {1: A(), 2: A()} + a = 0 + for v in dic.itervalues(): + a += isinstance(v, A) + return a + res = self.interpret(func, []) + assert res == 2 + + def test_dict_inst_items(self): + self._skip_oo('instances as keys') + class Empty: + pass + class A: + pass + class B(Empty): + pass + def func(): + dic0 = {Empty(): 2} + dic = {B(): A(), B(): A()} + items = dic.items() + b = 0 + a = 0 + for k, v in items: + b += isinstance(k, B) + a += isinstance(v, A) + return 3*b+a + res = self.interpret(func, []) + assert res == 8 + + def test_dict_inst_iteritems(self): + self._skip_oo('instances as values') + class Empty: + pass + class A: + pass + class B(Empty): + pass + def func(): + dic0 = {Empty(): 2} + dic = {B(): A(), B(): A()} + b = 0 + a = 0 + for k, v in dic.iteritems(): + b += isinstance(k, B) + a += isinstance(v, A) + return 3*b+a + res = self.interpret(func, []) + assert res == 8 + + def test_dict_items(self): + 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 = self.interpret(func, ()) + assert res == 1214 + + def test_dict_contains(self): + def func(): + dic = {' 4':1000, ' 8':200} + return ' 4' in dic and ' 9' not in dic + res = self.interpret(func, ()) + assert res is True + + def test_dict_contains_with_constant_dict(self): + self._skip_oo('mixing char and string') + dic = {'4':1000, ' 8':200} + def func(i): + return chr(i) in dic + res = self.interpret(func, [ord('4')]) + assert res is True + res = self.interpret(func, [1]) + assert res is False + + def test_dict_or_none(self): + class A: + pass + def negate(d): + return not d + def func(n): + a = A() + a.d = None + if n > 0: + a.d = {str(n): 1, "42": 2} + del a.d["42"] + return negate(a.d) + res = self.interpret(func, [10]) + assert res is False + res = self.interpret(func, [0]) + assert res is True + res = self.interpret(func, [42]) + assert res is True + + def test_int_dict(self): + def func(a, b): + dic = {12: 34} + dic[a] = 1000 + return dic.get(b, -123) + res = self.interpret(func, [12, 12]) + assert res == 1000 + res = self.interpret(func, [12, 13]) + assert res == -123 + res = self.interpret(func, [524, 12]) + assert res == 34 + res = self.interpret(func, [524, 524]) + assert res == 1000 + res = self.interpret(func, [524, 1036]) + assert res == -123 + + + + def test_id_instances_keys(self): + class A: + pass + class B(A): + pass + def f(): + a = A() + b = B() + d = {} + d[b] = 7 + d[a] = 3 + return len(d) + d[a] + d[b] + res = self.interpret(f, []) + assert res == 12 + + def test_captured_get(self): + get = {1:2}.get + def f(): + return get(1, 3)+get(2, 4) + res = self.interpret(f, []) + assert res == 6 + + def g(h): + return h(1, 3) + def f(): + return g(get) + + res = self.interpret(f, []) + assert res == 2 + + def test_specific_obscure_bug(self): + class A: pass + class B: pass # unrelated kinds of instances + def f(): + lst = [A()] + res1 = A() in lst + d2 = {B(): None, B(): None} + return res1+len(d2) + res = self.interpret(f, []) + assert res == 2 + + + def test_type_erase(self): + class A(object): + pass + class B(object): + pass + + def f(): + return {A(): B()}, {B(): A()} + + t = TranslationContext() + s = t.buildannotator().build_types(f, []) + rtyper = t.buildrtyper() + rtyper.specialize() + + s_AB_dic = s.items[0] + s_BA_dic = s.items[1] + + r_AB_dic = rtyper.getrepr(s_AB_dic) + r_BA_dic = rtyper.getrepr(s_AB_dic) + + assert r_AB_dic.lowleveltype == r_BA_dic.lowleveltype + + def test_tuple_dict(self): + def f(i): + d = {} + d[(1, 2)] = 4 + d[(1, 3)] = 6 + return d[(1, i)] + + res = self.interpret(f, [2]) + assert res == f(2) + + def test_dict_of_dict(self): + self._skip_oo('dict of dict') + def f(n): + d = {} + d[5] = d + d[6] = {} + return len(d[n]) + + res = self.interpret(f, [5]) + assert res == 2 + res = self.interpret(f, [6]) + assert res == 0 + + def test_access_in_try(self): + def f(d): + try: + return d[2] + except ZeroDivisionError: + return 42 + return -1 + def g(n): + d = {1: n, 2: 2*n} + return f(d) + res = self.interpret(g, [3]) + assert res == 6 + + def test_access_in_try_set(self): + def f(d): + try: + d[2] = 77 + except ZeroDivisionError: + return 42 + return -1 + def g(n): + d = {1: n} + f(d) + return d[2] + res = self.interpret(g, [3]) + assert res == 77 + + +class TestLLtype(BaseTestRdict, LLRtypeMixin): + def test_dict_but_not_with_char_keys(self): + def func(i): + d = {'h': i} + try: + return d['hello'] + except KeyError: + return 0 + res = self.interpret(func, [6]) + assert res == 0 + + def test_deleted_entry_reusage_with_colliding_hashes(self): + def lowlevelhash(value): + p = lltype.malloc(rstr.STR, len(value)) + for i in range(len(value)): + p.chars[i] = value[i] + return rstr.LLHelpers.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] + + char_by_hash = {} + base = rdict.DICT_INITSIZE + 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 = self.interpret(func, [ord(x), ord(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 = self.interpret(func2, [ord(x), ord(y)]) + for i in range(len(res.entries)): + assert not (res.entries[i].everused() and not res.entries[i].valid()) + + 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 + + if rdict.DICT_INITSIZE != 8: + py.test.skip("make dict tests more indepdent from initsize") + res = self.interpret(func3, [ord(char_by_hash[i][0]) + for i in range(rdict.DICT_INITSIZE)]) + count_frees = 0 + for i in range(len(res.entries)): + if not res.entries[i].everused(): + count_frees += 1 + assert count_frees >= 3 + + def test_dict_resize(self): + def func(want_empty): + d = {} + for i in range(rdict.DICT_INITSIZE): + d[chr(ord('a') + i)] = i + if want_empty: + for i in range(rdict.DICT_INITSIZE): + del d[chr(ord('a') + i)] + return d + res = self.interpret(func, [0]) + assert len(res.entries) > rdict.DICT_INITSIZE + res = self.interpret(func, [1]) + assert len(res.entries) == rdict.DICT_INITSIZE + + def test_dict_valid_resize(self): + # see if we find our keys after resize + def func(): + d = {} + # fill it up + for i in range(10): + d[str(i)] = 0 + # delete again + for i in range(10): + del d[str(i)] + res = 0 + # if it does not crash, we are fine. It crashes if you forget the hash field. + self.interpret(func, []) + + # ____________________________________________________________ + + def test_stress(self): + from pypy.annotation.dictdef import DictKey, DictValue + from pypy.annotation import model as annmodel + dictrepr = rdict.DictRepr(None, rint.signed_repr, rint.signed_repr, + DictKey(None, annmodel.SomeInteger()), + DictValue(None, annmodel.SomeInteger())) + dictrepr.setup() + l_dict = rdict.ll_newdict(dictrepr.DICT) + referencetable = [None] * 400 + referencelength = 0 + value = 0 + + def complete_check(): + for n, refvalue in zip(range(len(referencetable)), referencetable): + try: + gotvalue = rdict.ll_dict_getitem(l_dict, n) + except KeyError: + assert refvalue is None + else: + assert gotvalue == refvalue + + for x in not_really_random(): + n = int(x*100.0) # 0 <= x < 400 + op = repr(x)[-1] + if op <= '2' and referencetable[n] is not None: + rdict.ll_dict_delitem(l_dict, n) + referencetable[n] = None + referencelength -= 1 + elif op <= '6': + rdict.ll_dict_setitem(l_dict, n, value) + if referencetable[n] is None: + referencelength += 1 + referencetable[n] = value + value += 1 + else: + try: + gotvalue = rdict.ll_dict_getitem(l_dict, n) + except KeyError: + assert referencetable[n] is None + else: + assert gotvalue == referencetable[n] + if 1.38 <= x <= 1.39: + complete_check() + print 'current dict length:', referencelength + assert l_dict.num_items == referencelength + complete_check() + + # ____________________________________________________________ + + def test_opt_nullkeymarker(self): + def f(): + d = {"hello": None} + d["world"] = None + return "hello" in d, d + res = self.interpret(f, []) + assert res.item0 == True + DICT = lltype.typeOf(res.item1).TO + assert not hasattr(DICT.entries.TO.OF, 'f_everused')# non-None string keys + assert not hasattr(DICT.entries.TO.OF, 'f_valid') # strings have a dummy + + def test_opt_nullvaluemarker(self): + def f(n): + d = {-5: "abcd"} + d[123] = "def" + return len(d[n]), d + res = self.interpret(f, [-5]) + assert res.item0 == 4 + DICT = lltype.typeOf(res.item1).TO + assert not hasattr(DICT.entries.TO.OF, 'f_everused')# non-None str values + assert not hasattr(DICT.entries.TO.OF, 'f_valid') # strs have a dummy + + def test_opt_nonullmarker(self): + class A: + pass + def f(n): + if n > 5: + a = A() + else: + a = None + d = {a: -5441} + d[A()] = n+9872 + return d[a], d + res = self.interpret(f, [-5]) + assert res.item0 == -5441 + DICT = lltype.typeOf(res.item1).TO + assert hasattr(DICT.entries.TO.OF, 'f_everused') # can-be-None A instances + assert not hasattr(DICT.entries.TO.OF, 'f_valid')# with a dummy A instance + + res = self.interpret(f, [6]) + assert res.item0 == -5441 + + def test_opt_nonnegint_dummy(self): + def f(n): + d = {n: 12} + d[-87] = 24 + del d[n] + return len(d.copy()), d[-87], d + res = self.interpret(f, [5]) + assert res.item0 == 1 + assert res.item1 == 24 + DICT = lltype.typeOf(res.item2).TO + assert hasattr(DICT.entries.TO.OF, 'f_everused') # all ints can be zero + assert not hasattr(DICT.entries.TO.OF, 'f_valid')# nonneg int: dummy -1 + + def test_opt_no_dummy(self): + def f(n): + d = {n: 12} + d[-87] = -24 + del d[n] + return len(d.copy()), d[-87], d + res = self.interpret(f, [5]) + assert res.item0 == 1 + assert res.item1 == -24 + DICT = lltype.typeOf(res.item2).TO + assert hasattr(DICT.entries.TO.OF, 'f_everused') # all ints can be zero + assert hasattr(DICT.entries.TO.OF, 'f_valid') # no dummy available + + def test_opt_multiple_identical_dicts(self): + def f(n): + s = "x" * n + d1 = {s: 12} + d2 = {s: 24} + d3 = {s: 36} + d1["a"] = d2[s] # 24 + d3[s] += d1["a"] # 60 + d2["bc"] = d3[s] # 60 + return d2["bc"], d1, d2, d3 + res = self.interpret(f, [5]) + assert res.item0 == 60 + # all three dicts should use the same low-level type + assert lltype.typeOf(res.item1) == lltype.typeOf(res.item2) + assert lltype.typeOf(res.item1) == lltype.typeOf(res.item3) + + # ____________________________________________________________ + + + +class TestOOtype(BaseTestRdict, OORtypeMixin): def test_recursive(self): def func(i): @@ -901,3 +761,6 @@ res = self.interpret(func, [5]) assert res.ll_get(5) is res + + + From antocuni at codespeak.net Wed May 24 13:48:18 2006 From: antocuni at codespeak.net (antocuni at codespeak.net) Date: Wed, 24 May 2006 13:48:18 +0200 (CEST) Subject: [pypy-svn] r27647 - in pypy/dist/pypy/rpython: ootypesystem test Message-ID: <20060524114818.5D4F61006D@code0.codespeak.net> Author: antocuni Date: Wed May 24 13:48:04 2006 New Revision: 27647 Modified: pypy/dist/pypy/rpython/ootypesystem/ootype.py pypy/dist/pypy/rpython/ootypesystem/rclass.py pypy/dist/pypy/rpython/test/test_rdict.py Log: More little bugs fixed. Modified: pypy/dist/pypy/rpython/ootypesystem/ootype.py ============================================================================== --- pypy/dist/pypy/rpython/ootypesystem/ootype.py (original) +++ pypy/dist/pypy/rpython/ootypesystem/ootype.py Wed May 24 13:48:04 2006 @@ -296,10 +296,16 @@ }) self._setup_methods(generic_types) + def _enforce(self, value): + TYPE = typeOf(value) + if TYPE == Char: + return make_string(value) + else: + return BuiltinADTType._enforce(self, value) + # TODO: should it return _null or ''? def _defl(self): return make_string("") - def _example(self): return self._defl() Modified: pypy/dist/pypy/rpython/ootypesystem/rclass.py ============================================================================== --- pypy/dist/pypy/rpython/ootypesystem/rclass.py (original) +++ pypy/dist/pypy/rpython/ootypesystem/rclass.py Wed May 24 13:48:04 2006 @@ -233,6 +233,9 @@ ootype.addFields(self.lowleveltype, fields) + self.rbase = getinstancerepr(self.rtyper, self.classdef.basedef, True) + self.rbase.setup() + methods = {} classattributes = {} baseInstance = self.lowleveltype._superclass 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 Wed May 24 13:48:04 2006 @@ -188,7 +188,6 @@ assert res == 2 def test_dict_copy(self): - self._skip_oo('mixing char and string') def func(): # XXX this does not work if we use chars, only! dic = {'ab':1, 'b':2} @@ -205,7 +204,6 @@ assert res == 1 def test_dict_update(self): - self._skip_oo('mixing char and string') def func(): dic = {'ab':1000, 'b':200} d2 = {'b':30, 'cb':4} @@ -227,7 +225,6 @@ assert res == 14 def test_dict_inst_keys(self): - self._skip_oo('instances as keys') class Empty: pass class A(Empty): @@ -241,7 +238,6 @@ assert res == 3 def test_dict_inst_iterkeys(self): - self._skip_oo('instances as keys') class Empty: pass class A(Empty): @@ -265,7 +261,6 @@ assert res == 1202 def test_dict_inst_values(self): - self._skip_oo('instances as values') class A: pass def func(): @@ -276,7 +271,6 @@ assert res == 3 def test_dict_inst_itervalues(self): - self._skip_oo('instances as values') class A: pass def func(): @@ -289,7 +283,6 @@ assert res == 2 def test_dict_inst_items(self): - self._skip_oo('instances as keys') class Empty: pass class A: @@ -310,7 +303,6 @@ assert res == 8 def test_dict_inst_iteritems(self): - self._skip_oo('instances as values') class Empty: pass class A: @@ -348,7 +340,6 @@ assert res is True def test_dict_contains_with_constant_dict(self): - self._skip_oo('mixing char and string') dic = {'4':1000, ' 8':200} def func(i): return chr(i) in dic From cfbolz at codespeak.net Wed May 24 15:18:41 2006 From: cfbolz at codespeak.net (cfbolz at codespeak.net) Date: Wed, 24 May 2006 15:18:41 +0200 (CEST) Subject: [pypy-svn] r27649 - pypy/dist/pypy/translator/stackless Message-ID: <20060524131841.8B0E010074@code0.codespeak.net> Author: cfbolz Date: Wed May 24 15:18:40 2006 New Revision: 27649 Modified: pypy/dist/pypy/translator/stackless/code.py Log: fix typo in comment Modified: pypy/dist/pypy/translator/stackless/code.py ============================================================================== --- pypy/dist/pypy/translator/stackless/code.py (original) +++ pypy/dist/pypy/translator/stackless/code.py Wed May 24 15:18:40 2006 @@ -159,7 +159,7 @@ def ll_stack_capture(): if global_state.restart_substate == -1: - # normal entry point for stack_frames_depth() + # normal entry point for ll_stack_capture() # first unwind the stack in the usual way u = UnwindException() s = lltype.malloc(EMPTY_STATE).header From cfbolz at codespeak.net Wed May 24 18:22:34 2006 From: cfbolz at codespeak.net (cfbolz at codespeak.net) Date: Wed, 24 May 2006 18:22:34 +0200 (CEST) Subject: [pypy-svn] r27654 - in pypy/dist/pypy/translator: c/test stackless stackless/test Message-ID: <20060524162234.BBF2C10074@code0.codespeak.net> Author: cfbolz Date: Wed May 24 18:22:33 2006 New Revision: 27654 Modified: pypy/dist/pypy/translator/c/test/test_stackless.py pypy/dist/pypy/translator/stackless/test/test_depth.py pypy/dist/pypy/translator/stackless/transform.py Log: small optimization in stackless: don't safe state for tail calls. need to fix some tests, because they were tail calls, so the stack-depth was wrong :-). This makes pypy-c-stackless slightly smaller (125 kb less code). Modified: pypy/dist/pypy/translator/c/test/test_stackless.py ============================================================================== --- pypy/dist/pypy/translator/c/test/test_stackless.py (original) +++ pypy/dist/pypy/translator/c/test/test_stackless.py Wed May 24 18:22:33 2006 @@ -62,7 +62,7 @@ def f(n): g1() if n > 0: - res = f(n-1) + res = f(n-1) + 0 # make sure it is not a tail call else: res = stack_frames_depth() g2(g1) @@ -79,10 +79,10 @@ def test_stack_withptr(self): def f(n): if n > 0: - res = f(n-1) + res, dummy = f(n-1) else: - res = stack_frames_depth(), 1 - return res + res, dummy = stack_frames_depth(), 1 + return res, dummy def fn(): count0, _ = f(0) @@ -96,10 +96,10 @@ def f(n): if n > 0: stack_frames_depth() - res = f(n-1) + res, dummy = f(n-1) else: - res = stack_frames_depth(), 1 - return res + res, dummy = stack_frames_depth(), 1 + return res, dummy def fn(): count0, _ = f(0) @@ -112,10 +112,10 @@ def test_stackless_arguments(self): def f(n, d, t): if n > 0: - res = f(n-1, d, t) + a, b, c = f(n-1, d, t) else: - res = stack_frames_depth(), d, t - return res + a, b, c = stack_frames_depth(), d, t + return a, b, c def fn(): count0, d, t = f(0, 5.5, (1, 2)) Modified: pypy/dist/pypy/translator/stackless/test/test_depth.py ============================================================================== --- pypy/dist/pypy/translator/stackless/test/test_depth.py (original) +++ pypy/dist/pypy/translator/stackless/test/test_depth.py Wed May 24 18:22:33 2006 @@ -14,7 +14,7 @@ def f(n): g1() if n > 0: - res = f(n-1) + res = f(n-1) + 0 else: res = rstack.stack_frames_depth() g2(g1) @@ -34,7 +34,8 @@ def test_with_ptr(): def f(n): if n > 0: - res = f(n-1) + res, dummy = f(n-1) + return (res, dummy) else: res = rstack.stack_frames_depth(), 1 return res @@ -53,7 +54,8 @@ def test_manytimes(): def f(n): if n > 0: - res = f(n-1) + res, dummy = f(n-1) + return (res, dummy) else: res = rstack.stack_frames_depth(), 1 return res @@ -72,7 +74,8 @@ def test_arguments(): def f(n, d, t): if n > 0: - res = f(n-1, d, t) + res, y, z = f(n-1, d, t) + return res, y, z else: res = rstack.stack_frames_depth(), d, t return res @@ -95,3 +98,19 @@ res = llinterp_stackless_function(fn) assert res == 1 + +def test_eliminate_tail_calls(): + # make sure that when unwinding the stack there are no frames saved + # for tail calls + def f(n): + if n > 0: + res = f(n-1) + else: + res = rstack.stack_frames_depth() + return res + def fn(): + count0 = f(0) + count10 = f(10) + return count10 - count0 + res = llinterp_stackless_function(fn) + assert res == 0 Modified: pypy/dist/pypy/translator/stackless/transform.py ============================================================================== --- pypy/dist/pypy/translator/stackless/transform.py (original) +++ pypy/dist/pypy/translator/stackless/transform.py Wed May 24 18:22:33 2006 @@ -419,6 +419,15 @@ i += 1 continue + if (not stackless_op and i == len(block.operations) - 1 and + len(block.exits) == 1 and + block.exits[0].target is self.curr_graph.returnblock and + (block.exits[0].args[0].concretetype is lltype.Void or + block.exits[0].args[0] is op.result)): +# print "optimizing tail call %s in function %s" % (op, self.curr_graph.name) + i += 1 + continue + if i == len(block.operations) - 1 \ and block.exitswitch == model.c_last_exception: link = block.exits[0] From arigo at codespeak.net Wed May 24 20:43:36 2006 From: arigo at codespeak.net (arigo at codespeak.net) Date: Wed, 24 May 2006 20:43:36 +0200 (CEST) Subject: [pypy-svn] r27657 - pypy/dist/pypy/translator/tool Message-ID: <20060524184336.2381C1006E@code0.codespeak.net> Author: arigo Date: Wed May 24 20:43:35 2006 New Revision: 27657 Modified: pypy/dist/pypy/translator/tool/lltracker.py Log: Modified the debug_view in such a way that we can see the pointers that we passed in as argument, so e.g. it is clear when we pass it twice the same pointer (as is the case in my failing test, where the supposely cloned coroutine is actually the same object as its original). Modified: pypy/dist/pypy/translator/tool/lltracker.py ============================================================================== --- pypy/dist/pypy/translator/tool/lltracker.py (original) +++ pypy/dist/pypy/translator/tool/lltracker.py Wed May 24 20:43:35 2006 @@ -121,25 +121,30 @@ """Invoke a dot+pygame object reference tracker.""" lst = [MARKER] size_gc_header = None + seen = {} for ll_object in ll_objects: if isinstance(ll_object, llmemory.GCHeaderOffset): size_gc_header = ll_object continue - if isinstance(lltype.typeOf(ll_object), lltype.Ptr): - ptr = lltype.normalizeptr(ll_object) - if ptr is not None: - ll_object = ptr._obj - else: - ll_object = None - if ll_object is not None and ll_object not in lst: + #if isinstance(lltype.typeOf(ll_object), lltype.Ptr): + # ptr = lltype.normalizeptr(ll_object) + # if ptr is not None: + # ll_object = ptr._obj + # else: + # ll_object = None + if ll_object is not None and id(ll_object) not in seen: lst.append(ll_object) + seen[id(ll_object)] = ll_object page = LLRefTrackerPage(lst, size_gc_header) - if len(lst) == 2: - # auto-expand one level + # auto-expand one level, for now + auto_expand = 1 + for i in range(auto_expand): page = page.content() - for name, value in page.enum_content(lst[1]): - if not isinstance(value, str) and value not in lst: - lst.append(value) + for ll_object in lst[1:]: + for name, value in page.enum_content(ll_object): + if not isinstance(value, str) and id(value) not in seen: + lst.append(value) + seen[id(value)] = value page = page.newpage(lst) page.display() From njriley at codespeak.net Wed May 24 20:46:40 2006 From: njriley at codespeak.net (njriley at codespeak.net) Date: Wed, 24 May 2006 20:46:40 +0200 (CEST) Subject: [pypy-svn] r27658 - in pypy/branch/njriley-trans/pypy: module/trans rpython rpython/module translator/c translator/c/src Message-ID: <20060524184640.4EEC01006E@code0.codespeak.net> Author: njriley Date: Wed May 24 20:46:39 2006 New Revision: 27658 Modified: pypy/branch/njriley-trans/pypy/module/trans/__init__.py pypy/branch/njriley-trans/pypy/module/trans/interp_trans.py pypy/branch/njriley-trans/pypy/module/trans/rtrans.py pypy/branch/njriley-trans/pypy/rpython/extfunctable.py pypy/branch/njriley-trans/pypy/rpython/module/ll_trans.py pypy/branch/njriley-trans/pypy/translator/c/extfunc.py pypy/branch/njriley-trans/pypy/translator/c/src/ll_trans.h Log: Add rtrans/trans.reset_stats so we get more accurate numbers Modified: pypy/branch/njriley-trans/pypy/module/trans/__init__.py ============================================================================== --- pypy/branch/njriley-trans/pypy/module/trans/__init__.py (original) +++ pypy/branch/njriley-trans/pypy/module/trans/__init__.py Wed May 24 20:46:39 2006 @@ -7,11 +7,12 @@ } interpleveldefs = { - 'begin' : 'interp_trans.begin', - 'end' : 'interp_trans.end', - 'abort' : 'interp_trans.abort', - 'pause' : 'interp_trans.pause', - 'unpause' : 'interp_trans.unpause', - 'verbose' : 'interp_trans.verbose', - 'is_active' : 'interp_trans.is_active', + 'begin' : 'interp_trans.begin', + 'end' : 'interp_trans.end', + 'abort' : 'interp_trans.abort', + 'pause' : 'interp_trans.pause', + 'unpause' : 'interp_trans.unpause', + 'verbose' : 'interp_trans.verbose', + 'is_active' : 'interp_trans.is_active', + 'reset_stats' : 'interp_trans.reset_stats', } Modified: pypy/branch/njriley-trans/pypy/module/trans/interp_trans.py ============================================================================== --- pypy/branch/njriley-trans/pypy/module/trans/interp_trans.py (original) +++ pypy/branch/njriley-trans/pypy/module/trans/interp_trans.py Wed May 24 20:46:39 2006 @@ -28,3 +28,7 @@ def is_active(space): return space.wrap(rtrans.is_active()) + +def reset_stats(space): + rtrans.reset_stats() + return space.w_None Modified: pypy/branch/njriley-trans/pypy/module/trans/rtrans.py ============================================================================== --- pypy/branch/njriley-trans/pypy/module/trans/rtrans.py (original) +++ pypy/branch/njriley-trans/pypy/module/trans/rtrans.py Wed May 24 20:46:39 2006 @@ -29,3 +29,6 @@ def is_active(): os.write(2, '= rtrans.is_active\n') return False + +def reset_stats(): + os.write(2, '= rtrans.reset_stats\n') Modified: pypy/branch/njriley-trans/pypy/rpython/extfunctable.py ============================================================================== --- pypy/branch/njriley-trans/pypy/rpython/extfunctable.py (original) +++ pypy/branch/njriley-trans/pypy/rpython/extfunctable.py Wed May 24 20:46:39 2006 @@ -277,6 +277,7 @@ declare(rtrans.enable, noneannotation, 'll_trans/enable') declare(rtrans.disable, noneannotation, 'll_trans/disable') declare(rtrans.is_active, bool, 'll_trans/is_active') +declare(rtrans.reset_stats, noneannotation, 'll_trans/reset_stats') # ___________________________________________________________ # javascript Modified: pypy/branch/njriley-trans/pypy/rpython/module/ll_trans.py ============================================================================== --- pypy/branch/njriley-trans/pypy/rpython/module/ll_trans.py (original) +++ pypy/branch/njriley-trans/pypy/rpython/module/ll_trans.py Wed May 24 20:46:39 2006 @@ -33,3 +33,7 @@ def ll_trans_is_active(): return False ll_trans_is_active.suggested_primitive = True + +def ll_trans_reset_stats(): + pass +ll_trans_reset_stats.suggested_primitive = True Modified: pypy/branch/njriley-trans/pypy/translator/c/extfunc.py ============================================================================== --- pypy/branch/njriley-trans/pypy/translator/c/extfunc.py (original) +++ pypy/branch/njriley-trans/pypy/translator/c/extfunc.py Wed May 24 20:46:39 2006 @@ -63,6 +63,7 @@ ll_trans.ll_trans_verbose: 'LL_trans_verbose', ll_trans.ll_trans_enable: 'LL_trans_enable', ll_trans.ll_trans_disable: 'LL_trans_disable', + ll_trans.ll_trans_reset_stats: 'LL_trans_reset_stats', ll_trans.ll_trans_is_active: 'LL_trans_is_active', ll_tsc.ll_tsc_read: 'LL_tsc_read', ll_tsc.ll_tsc_read_diff: 'LL_tsc_read_diff', Modified: pypy/branch/njriley-trans/pypy/translator/c/src/ll_trans.h ============================================================================== --- pypy/branch/njriley-trans/pypy/translator/c/src/ll_trans.h (original) +++ pypy/branch/njriley-trans/pypy/translator/c/src/ll_trans.h Wed May 24 20:46:39 2006 @@ -124,4 +124,10 @@ return ret_val; } +void +LL_trans_reset_stats(void) +{ + XACT_DUMP_STATS(2); +} + #endif /* PYPY_NOT_MAIN_FILE */ From njriley at codespeak.net Wed May 24 20:47:47 2006 From: njriley at codespeak.net (njriley at codespeak.net) Date: Wed, 24 May 2006 20:47:47 +0200 (CEST) Subject: [pypy-svn] r27659 - pypy/branch/njriley-trans/pypy/translator/c Message-ID: <20060524184747.33CBA1006E@code0.codespeak.net> Author: njriley Date: Wed May 24 20:47:46 2006 New Revision: 27659 Modified: pypy/branch/njriley-trans/pypy/translator/c/genc.py Log: Make Simics symtable module happy by generating STABS compatible files Modified: pypy/branch/njriley-trans/pypy/translator/c/genc.py ============================================================================== --- pypy/branch/njriley-trans/pypy/translator/c/genc.py (original) +++ pypy/branch/njriley-trans/pypy/translator/c/genc.py Wed May 24 20:47:46 2006 @@ -279,7 +279,8 @@ # ____________________________________________________________ -SPLIT_CRITERIA = 65535 # support VC++ 7.2 +SPLIT_CRITERIA = 32767 +#SPLIT_CRITERIA = 65535 # support VC++ 7.2 #SPLIT_CRITERIA = 32767 # enable to support VC++ 6.0 MARKER = '/*/*/' # provide an easy way to split after generating @@ -357,10 +358,11 @@ yield self.uniquecname(basecname), subiter() def gen_readable_parts_of_source(self, f): - if py.std.sys.platform != "win32": - split_criteria_big = SPLIT_CRITERIA * 4 - else: - split_criteria_big = SPLIT_CRITERIA + # if py.std.sys.platform != "win32": + # split_criteria_big = SPLIT_CRITERIA * 4 + # else: + # XXX njr hack - STABS doesn't support >65535 lines either + split_criteria_big = SPLIT_CRITERIA if self.one_source_file: return gen_readable_parts_of_main_c_file(f, self.database, self.preimpl) From njriley at codespeak.net Wed May 24 20:48:14 2006 From: njriley at codespeak.net (njriley at codespeak.net) Date: Wed, 24 May 2006 20:48:14 +0200 (CEST) Subject: [pypy-svn] r27660 - in pypy/branch/njriley-trans/pypy: rpython/lltypesystem translator/c Message-ID: <20060524184814.8B3941006E@code0.codespeak.net> Author: njriley Date: Wed May 24 20:48:13 2006 New Revision: 27660 Modified: pypy/branch/njriley-trans/pypy/rpython/lltypesystem/rclass.py pypy/branch/njriley-trans/pypy/translator/c/exceptiontransform.py pypy/branch/njriley-trans/pypy/translator/c/node.py Log: Make exceptions thread-local Modified: pypy/branch/njriley-trans/pypy/rpython/lltypesystem/rclass.py ============================================================================== --- pypy/branch/njriley-trans/pypy/rpython/lltypesystem/rclass.py (original) +++ pypy/branch/njriley-trans/pypy/rpython/lltypesystem/rclass.py Wed May 24 20:48:13 2006 @@ -342,10 +342,10 @@ MkStruct = GcStruct else: MkStruct = Struct - + object_type = MkStruct(self.classdef.name, ('super', self.rbase.object_type), - *llfields) + *llfields, **dict(hints=self.gethints())) self.object_type.become(object_type) allinstancefields.update(self.rbase.allinstancefields) allinstancefields.update(fields) @@ -380,6 +380,9 @@ def getflavor(self): return self.classdef.classdesc.read_attribute('_alloc_flavor_', Constant('gc')).value + def gethints(self): + return self.classdef.classdesc.read_attribute('_rpython_hints_', Constant({})).value + def null_instance(self): return nullptr(self.object_type) Modified: pypy/branch/njriley-trans/pypy/translator/c/exceptiontransform.py ============================================================================== --- pypy/branch/njriley-trans/pypy/translator/c/exceptiontransform.py (original) +++ pypy/branch/njriley-trans/pypy/translator/c/exceptiontransform.py Wed May 24 20:48:13 2006 @@ -42,7 +42,7 @@ l2a = annmodel.lltype_to_annotation class ExcData(object): - pass + _rpython_hints_ = {'thread_local': True} #exc_type = lltype.nullptr(self.exc_data.lltype_of_exception_type.TO) #exc_value = lltype.nullptr(self.exc_data.lltype_of_exception_value.TO) Modified: pypy/branch/njriley-trans/pypy/translator/c/node.py ============================================================================== --- pypy/branch/njriley-trans/pypy/translator/c/node.py (original) +++ pypy/branch/njriley-trans/pypy/translator/c/node.py Wed May 24 20:48:13 2006 @@ -365,15 +365,18 @@ self.ptrname = '((%s)(void*)%s)' % (cdecl(ptrtypename, ''), self.ptrname) + def declaration(self): + decl = cdecl(self.implementationtypename, self.name) + if hasattr(self.T, '_hints') and self.T._hints.get('thread_local'): + decl = '__thread ' + decl # XXX make conditional + return decl + def forward_declaration(self): - yield '%s;' % ( - cdecl(self.implementationtypename, self.name)) + yield 'extern %s;' % self.declaration() def implementation(self): lines = list(self.initializationexpr()) - lines[0] = '%s = %s' % ( - cdecl(self.implementationtypename, self.name), - lines[0]) + lines[0] = '%s = %s' % (self.declaration(), lines[0]) lines[-1] += ';' return lines From arigo at codespeak.net Wed May 24 21:24:04 2006 From: arigo at codespeak.net (arigo at codespeak.net) Date: Wed, 24 May 2006 21:24:04 +0200 (CEST) Subject: [pypy-svn] r27661 - in pypy/dist/pypy: interpreter module/stackless module/stackless/test translator/c/test Message-ID: <20060524192404.4F3FC1006E@code0.codespeak.net> Author: arigo Date: Wed May 24 21:24:01 2006 New Revision: 27661 Added: pypy/dist/pypy/module/stackless/interp_clonable.py (contents, props changed) pypy/dist/pypy/module/stackless/test/test_interp_clonable.py (contents, props changed) Modified: pypy/dist/pypy/interpreter/executioncontext.py pypy/dist/pypy/module/stackless/coroutine.py pypy/dist/pypy/module/stackless/interp_coroutine.py pypy/dist/pypy/module/stackless/test/test_interp_coroutine.py pypy/dist/pypy/translator/c/test/test_stackless.py Log: Clonable coroutines. The first test passes, but fork() is still buggy. Modified: pypy/dist/pypy/interpreter/executioncontext.py ============================================================================== --- pypy/dist/pypy/interpreter/executioncontext.py (original) +++ pypy/dist/pypy/interpreter/executioncontext.py Wed May 24 21:24:01 2006 @@ -45,17 +45,18 @@ coobj.is_tracing = 0 subcontext_new = staticmethod(subcontext_new) - def subcontext_switch(self, current, next): - current.framestack = self.framestack - current.w_tracefunc = self.w_tracefunc - current.w_profilefunc = self.w_profilefunc - current.is_tracing = self.is_tracing - + def subcontext_enter(self, next): self.framestack = next.framestack self.w_tracefunc = next.w_tracefunc self.w_profilefunc = next.w_profilefunc self.is_tracing = next.is_tracing + def subcontext_leave(self, current): + current.framestack = self.framestack + current.w_tracefunc = self.w_tracefunc + current.w_profilefunc = self.w_profilefunc + current.is_tracing = self.is_tracing + # coroutine: I think this is all, folks! def get_builtin(self): Modified: pypy/dist/pypy/module/stackless/coroutine.py ============================================================================== --- pypy/dist/pypy/module/stackless/coroutine.py (original) +++ pypy/dist/pypy/module/stackless/coroutine.py Wed May 24 21:24:01 2006 @@ -76,14 +76,19 @@ if self.frame is None: raise OperationError(space.w_ValueError, space.wrap( "cannot switch to an unbound Coroutine")) - state = self.costate - ec = space.getexecutioncontext() - ec.subcontext_switch(state.current, self) self.switch() - ec.subcontext_switch(state.last, state.current) + state = self.costate w_ret, state.w_tempval = state.w_tempval, space.w_None return w_ret + def hello(self): + ec = self.space.getexecutioncontext() + ec.subcontext_enter(self) + + def goodbye(self): + ec = self.space.getexecutioncontext() + ec.subcontext_leave(self) + def w_kill(self): self.kill() Added: pypy/dist/pypy/module/stackless/interp_clonable.py ============================================================================== --- (empty file) +++ pypy/dist/pypy/module/stackless/interp_clonable.py Wed May 24 21:24:01 2006 @@ -0,0 +1,53 @@ +from pypy.module.stackless.interp_coroutine import Coroutine, AbstractThunk +from pypy.rpython.rgc import gc_swap_pool, gc_clone + + +class ClonableCoroutine(Coroutine): + local_pool = None + + def hello(self): + self.saved_pool = gc_swap_pool(self.local_pool) + + def goodbye(self): + self.local_pool = gc_swap_pool(self.saved_pool) + + def clone(self): + if self.getcurrent() is self: + raise RuntimeError("clone() cannot clone the current coroutine; " + "use fork() instead") + if self.local_pool is None: # force it now + self.local_pool = gc_swap_pool(gc_swap_pool(None)) + # cannot gc_clone() directly self, because it is not in its own + # local_pool. Moreover, it has a __del__, which cloning doesn't + # support properly at the moment. + copy = ClonableCoroutine(self.costate) + copy.parent = self.parent + copy.frame, copy.local_pool = gc_clone(self.frame, self.local_pool) + return copy + + +class ForkThunk(AbstractThunk): + def __init__(self, coroutine): + self.coroutine = coroutine + self.newcoroutine = None + def call(self): + oldcoro = self.coroutine + self.coroutine = None + self.newcoroutine = oldcoro.clone() + +def fork(): + """Fork, as in the Unix fork(): the call returns twice, and the return + value of the call is either the new 'child' coroutine object (if returning + into the parent), or None (if returning into the child). This returns + into the parent first, which can switch to the child later. + """ + current = ClonableCoroutine.getcurrent() + if not isinstance(current, ClonableCoroutine): + raise RuntimeError("fork() in a non-clonable coroutine") + thunk = ForkThunk(current) + coro_fork = ClonableCoroutine() + coro_fork.bind(thunk) + coro_fork.switch() + # we resume here twice. The following would need explanations about + # why it returns the correct thing in both the parent and the child... + return thunk.newcoroutine Modified: pypy/dist/pypy/module/stackless/interp_coroutine.py ============================================================================== --- pypy/dist/pypy/module/stackless/interp_coroutine.py (original) +++ pypy/dist/pypy/module/stackless/interp_coroutine.py Wed May 24 21:24:01 2006 @@ -39,8 +39,13 @@ self.current = self.main = self.last = None def update(self, new): - self.last, self.current = self.current, new + old = self.current + if old is not None: + old.goodbye() + self.last, self.current = old, new frame, new.frame = new.frame, None + if new is not None: + new.hello() return frame class CoState(BaseCoState): @@ -186,6 +191,12 @@ return costate.current getcurrent = staticmethod(getcurrent) + def hello(self): + "Called when execution is transferred into this coroutine." + + def goodbye(self): + "Called just before execution is transferred away from this coroutine." + costate = None costate = CoState() Added: pypy/dist/pypy/module/stackless/test/test_interp_clonable.py ============================================================================== --- (empty file) +++ pypy/dist/pypy/module/stackless/test/test_interp_clonable.py Wed May 24 21:24:01 2006 @@ -0,0 +1,83 @@ +""" +testing cloning +""" + +from pypy.translator.c import gc +from pypy.rpython.memory import gctransform +from pypy.rpython.memory.test import test_transformed_gc +from pypy.module.stackless.interp_coroutine import costate +from pypy.module.stackless.interp_clonable import ClonableCoroutine +from pypy.module.stackless.interp_clonable import AbstractThunk, fork + + +class TestClonableCoroutine(test_transformed_gc.GCTest): + + class gcpolicy(gc.StacklessFrameworkGcPolicy): + class transformerclass(gctransform.StacklessFrameworkGCTransformer): + GC_PARAMS = {'start_heap_size': 4096 } + + def test_clone(self): + class T(AbstractThunk): + def __init__(self, result): + self.result = result + def call(self): + self.result.append(2) + costate.main.switch() + self.result.append(4) + def f(): + result = [] + coro = ClonableCoroutine() + coro.bind(T(result)) + result.append(1) + coro.switch() + coro2 = coro.clone() + result.append(3) + coro2.switch() + result.append(5) + coro.switch() + result.append(6) + n = 0 + for i in result: + n = n*10 + i + return n + + run = self.runner(f) + res = run([]) + assert res == 1234546 + + def test_fork(self): + import py; py.test.skip("in-progress") + class T(AbstractThunk): + def __init__(self, result): + self.result = result + def call(self): + localdata = [10] + self.result.append(2) + newcoro = fork() + localdata.append(20) + if newcoro is not None: + # in the parent + self.result.append(3) + newcoro.switch() + else: + # in the child + self.result.append(4) + localdata.append(30) + self.result.append(localdata != [10, 20, 30]) + def f(): + result = [] + coro = ClonableCoroutine() + coro.bind(T(result)) + result.append(1) + coro.switch() + result.append(5) + coro.switch() # resume after newcoro.switch() + result.append(6) + n = 0 + for i in result: + n = n*10 + i + return n + + run = self.runner(f) + res = run([]) + assert res == 12340506 Modified: pypy/dist/pypy/module/stackless/test/test_interp_coroutine.py ============================================================================== --- pypy/dist/pypy/module/stackless/test/test_interp_coroutine.py (original) +++ pypy/dist/pypy/module/stackless/test/test_interp_coroutine.py Wed May 24 21:24:01 2006 @@ -15,10 +15,14 @@ backendopt = True stacklessmode = True gcpolicy = gc.BoehmGcPolicy + Coroutine = Coroutine def setup_meth(self): costate.__init__() + def _freeze_(self): # for 'self.Coroutine' + return True + def test_coroutine(self): def g(lst, coros): @@ -48,8 +52,8 @@ def f(): lst = [1] coro_f = costate.main - coro_g = Coroutine() - coro_h = Coroutine() + coro_g = self.Coroutine() + coro_h = self.Coroutine() coros = [coro_f, coro_g, coro_h] thunk_g = T(g, lst, coros) output('binding g after f set 1') @@ -116,8 +120,8 @@ def f1(coro_f1): lst = [1] - coro_g = Coroutine() - coro_h = Coroutine() + coro_g = self.Coroutine() + coro_h = self.Coroutine() coros = [coro_f1, coro_g, coro_h] thunk_g = T(g, lst, coros) output('binding g after f1 set 1') @@ -143,7 +147,7 @@ def f(): coro_f = costate.main - coro_f1 = Coroutine() + coro_f1 = self.Coroutine() thunk_f1 = T1(f1, coro_f1) output('binding f1 after f set 1') coro_f1.bind(thunk_f1) @@ -171,7 +175,7 @@ costate.main.switch() def f(): - coro_g = Coroutine() + coro_g = self.Coroutine() thunk_g = T(g, 42) coro_g.bind(thunk_g) coro_g.switch() @@ -182,7 +186,7 @@ coro_g.kill() res *= 10 res |= coro_g.frame is None - coro_g = Coroutine() + coro_g = self.Coroutine() thunk_g = T(g, -42) coro_g.bind(thunk_g) try: @@ -246,8 +250,8 @@ def pre_order_eq(t1, t2): objects = [] - producer = Coroutine() - consumer = Coroutine() + producer = self.Coroutine() + consumer = self.Coroutine() producer.bind(Producer(t1, objects, consumer)) cons = Consumer(t2, objects, producer) Modified: pypy/dist/pypy/translator/c/test/test_stackless.py ============================================================================== --- pypy/dist/pypy/translator/c/test/test_stackless.py (original) +++ pypy/dist/pypy/translator/c/test/test_stackless.py Wed May 24 21:24:01 2006 @@ -14,14 +14,13 @@ def setup_class(cls): import py - if cls.gcpolicy is None: + if cls.gcpolicy in (None, gc.RefcountingGcPolicy): # to re-enable this, remove the two characters 'gc' in the # declaregcptrtype(rstack.frame_stack_top,...) call in # rpython/extfunctable. Doing so breaks translator/stackless/. import py py.test.skip("stackless + refcounting doesn't work any more for now") - else: - assert cls.gcpolicy is gc.BoehmGcPolicy + elif cls.gcpolicy is gc.BoehmGcPolicy: from pypy.translator.tool.cbuild import check_boehm_presence if not check_boehm_presence(): py.test.skip("Boehm GC not present") From ac at codespeak.net Wed May 24 22:18:31 2006 From: ac at codespeak.net (ac at codespeak.net) Date: Wed, 24 May 2006 22:18:31 +0200 (CEST) Subject: [pypy-svn] r27662 - pypy/dist/pypy/module/unicodedata Message-ID: <20060524201831.D4C3B1006E@code0.codespeak.net> Author: ac Date: Wed May 24 22:18:25 2006 New Revision: 27662 Modified: pypy/dist/pypy/module/unicodedata/generate_unicodedb.py pypy/dist/pypy/module/unicodedata/unicodedb.py Log: Update to Unicode 4.1 as per CPython 2.5 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 May 24 22:18:25 2006 @@ -2,6 +2,17 @@ MAXUNICODE = 0x10FFFF # the value of sys.maxunicode of wide Python builds +class Fraction: + def __init__(self, numerator, denominator): + self.numerator = numerator + self.denominator = denominator + + def __repr__(self): + return '%r / %r' % (self.numerator, self.denominator) + + def __str__(self): + return repr(self) + class Unicodechar: def __init__(self, data): if not data[1] or data[1][0] == '<' and data[1][-1] == '>': @@ -39,7 +50,7 @@ if data[8]: try: numerator, denomenator = data[8].split('/') - self.numeric = float(numerator) / float(denomenator) + self.numeric = Fraction(float(numerator), float(denomenator)) except ValueError: self.numeric = float(data[8]) self.mirrored = (data[9] == 'Y') Modified: pypy/dist/pypy/module/unicodedata/unicodedb.py ============================================================================== --- pypy/dist/pypy/module/unicodedata/unicodedb.py (original) +++ pypy/dist/pypy/module/unicodedata/unicodedb.py Wed May 24 22:18:25 2006 @@ -1,8 +1,8 @@ # UNICODE CHARACTER DATABASE # This file was generated with the command: -# D:\pypy\dist\pypy\module\unicodedata\generate_unicodedb.py -o unicodedb.py UnicodeData-3.2.0.txt CompositionExclusions-3.2.0.txt EastAsianWidth-3.2.0.txt +# ./generate_unicodedb.py -o unicodedb.py UnicodeData-4.1.0.txt CompositionExclusions-4.1.0.txt EastAsianWidth-4.1.0.txt -version = '3.2.0' +version = '4.1.0' _charnames = { 32: 'SPACE', @@ -485,6 +485,7 @@ 542: 'LATIN CAPITAL LETTER H WITH CARON', 543: 'LATIN SMALL LETTER H WITH CARON', 544: 'LATIN CAPITAL LETTER N WITH LONG RIGHT LEG', +545: 'LATIN SMALL LETTER D WITH CURL', 546: 'LATIN CAPITAL LETTER OU', 547: 'LATIN SMALL LETTER OU', 548: 'LATIN CAPITAL LETTER Z WITH HOOK', @@ -503,6 +504,20 @@ 561: 'LATIN SMALL LETTER O WITH DOT ABOVE AND MACRON', 562: 'LATIN CAPITAL LETTER Y WITH MACRON', 563: 'LATIN SMALL LETTER Y WITH MACRON', +564: 'LATIN SMALL LETTER L WITH CURL', +565: 'LATIN SMALL LETTER N WITH CURL', +566: 'LATIN SMALL LETTER T WITH CURL', +567: 'LATIN SMALL LETTER DOTLESS J', +568: 'LATIN SMALL LETTER DB DIGRAPH', +569: 'LATIN SMALL LETTER QP DIGRAPH', +570: 'LATIN CAPITAL LETTER A WITH STROKE', +571: 'LATIN CAPITAL LETTER C WITH STROKE', +572: 'LATIN SMALL LETTER C WITH STROKE', +573: 'LATIN CAPITAL LETTER L WITH BAR', +574: 'LATIN CAPITAL LETTER T WITH DIAGONAL STROKE', +575: 'LATIN SMALL LETTER S WITH SWASH TAIL', +576: 'LATIN SMALL LETTER Z WITH SWASH TAIL', +577: 'LATIN CAPITAL LETTER GLOTTAL STOP', 592: 'LATIN SMALL LETTER TURNED A', 593: 'LATIN SMALL LETTER ALPHA', 594: 'LATIN SMALL LETTER TURNED ALPHA', @@ -597,6 +612,8 @@ 683: 'LATIN SMALL LETTER LZ DIGRAPH', 684: 'LATIN LETTER BILABIAL PERCUSSIVE', 685: 'LATIN LETTER BIDENTAL PERCUSSIVE', +686: 'LATIN SMALL LETTER TURNED H WITH FISHHOOK', +687: 'LATIN SMALL LETTER TURNED H WITH FISHHOOK AND TAIL', 688: 'MODIFIER LETTER SMALL H', 689: 'MODIFIER LETTER SMALL H WITH HOOK', 690: 'MODIFIER LETTER SMALL J', @@ -660,6 +677,23 @@ 748: 'MODIFIER LETTER VOICING', 749: 'MODIFIER LETTER UNASPIRATED', 750: 'MODIFIER LETTER DOUBLE APOSTROPHE', +751: 'MODIFIER LETTER LOW DOWN ARROWHEAD', +752: 'MODIFIER LETTER LOW UP ARROWHEAD', +753: 'MODIFIER LETTER LOW LEFT ARROWHEAD', +754: 'MODIFIER LETTER LOW RIGHT ARROWHEAD', +755: 'MODIFIER LETTER LOW RING', +756: 'MODIFIER LETTER MIDDLE GRAVE ACCENT', +757: 'MODIFIER LETTER MIDDLE DOUBLE GRAVE ACCENT', +758: 'MODIFIER LETTER MIDDLE DOUBLE ACUTE ACCENT', +759: 'MODIFIER LETTER LOW TILDE', +760: 'MODIFIER LETTER RAISED COLON', +761: 'MODIFIER LETTER BEGIN HIGH TONE', +762: 'MODIFIER LETTER END HIGH TONE', +763: 'MODIFIER LETTER BEGIN LOW TONE', +764: 'MODIFIER LETTER END LOW TONE', +765: 'MODIFIER LETTER SHELF', +766: 'MODIFIER LETTER OPEN SHELF', +767: 'MODIFIER LETTER LOW LEFT ARROW', 768: 'COMBINING GRAVE ACCENT', 769: 'COMBINING ACUTE ACCENT', 770: 'COMBINING CIRCUMFLEX ACCENT', @@ -740,6 +774,22 @@ 845: 'COMBINING LEFT RIGHT ARROW BELOW', 846: 'COMBINING UPWARDS ARROW BELOW', 847: 'COMBINING GRAPHEME JOINER', +848: 'COMBINING RIGHT ARROWHEAD ABOVE', +849: 'COMBINING LEFT HALF RING ABOVE', +850: 'COMBINING FERMATA', +851: 'COMBINING X BELOW', +852: 'COMBINING LEFT ARROWHEAD BELOW', +853: 'COMBINING RIGHT ARROWHEAD BELOW', +854: 'COMBINING RIGHT ARROWHEAD AND UP ARROWHEAD BELOW', +855: 'COMBINING RIGHT HALF RING ABOVE', +856: 'COMBINING DOT ABOVE RIGHT', +857: 'COMBINING ASTERISK BELOW', +858: 'COMBINING DOUBLE RING BELOW', +859: 'COMBINING ZIGZAG ABOVE', +860: 'COMBINING DOUBLE BREVE BELOW', +861: 'COMBINING DOUBLE BREVE', +862: 'COMBINING DOUBLE MACRON', +863: 'COMBINING DOUBLE MACRON BELOW', 864: 'COMBINING DOUBLE TILDE', 865: 'COMBINING DOUBLE INVERTED BREVE', 866: 'COMBINING DOUBLE RIGHTWARDS ARROW BELOW', @@ -871,6 +921,15 @@ 1012: 'GREEK CAPITAL THETA SYMBOL', 1013: 'GREEK LUNATE EPSILON SYMBOL', 1014: 'GREEK REVERSED LUNATE EPSILON SYMBOL', +1015: 'GREEK CAPITAL LETTER SHO', +1016: 'GREEK SMALL LETTER SHO', +1017: 'GREEK CAPITAL LUNATE SIGMA SYMBOL', +1018: 'GREEK CAPITAL LETTER SAN', +1019: 'GREEK SMALL LETTER SAN', +1020: 'GREEK RHO WITH STROKE SYMBOL', +1021: 'GREEK CAPITAL REVERSED LUNATE SIGMA SYMBOL', +1022: 'GREEK CAPITAL DOTTED LUNATE SIGMA SYMBOL', +1023: 'GREEK CAPITAL REVERSED DOTTED LUNATE SIGMA SYMBOL', 1024: 'CYRILLIC CAPITAL LETTER IE WITH GRAVE', 1025: 'CYRILLIC CAPITAL LETTER IO', 1026: 'CYRILLIC CAPITAL LETTER DJE', @@ -1115,6 +1174,8 @@ 1267: 'CYRILLIC SMALL LETTER U WITH DOUBLE ACUTE', 1268: 'CYRILLIC CAPITAL LETTER CHE WITH DIAERESIS', 1269: 'CYRILLIC SMALL LETTER CHE WITH DIAERESIS', +1270: 'CYRILLIC CAPITAL LETTER GHE WITH DESCENDER', +1271: 'CYRILLIC SMALL LETTER GHE WITH DESCENDER', 1272: 'CYRILLIC CAPITAL LETTER YERU WITH DIAERESIS', 1273: 'CYRILLIC SMALL LETTER YERU WITH DIAERESIS', 1280: 'CYRILLIC CAPITAL LETTER KOMI DE', @@ -1236,6 +1297,7 @@ 1439: 'HEBREW ACCENT QARNEY PARA', 1440: 'HEBREW ACCENT TELISHA GEDOLA', 1441: 'HEBREW ACCENT PAZER', +1442: 'HEBREW ACCENT ATNAH HAFUKH', 1443: 'HEBREW ACCENT MUNAH', 1444: 'HEBREW ACCENT MAHAPAKH', 1445: 'HEBREW ACCENT MERKHA', @@ -1269,6 +1331,9 @@ 1474: 'HEBREW POINT SIN DOT', 1475: 'HEBREW PUNCTUATION SOF PASUQ', 1476: 'HEBREW MARK UPPER DOT', +1477: 'HEBREW MARK LOWER DOT', +1478: 'HEBREW PUNCTUATION NUN HAFUKHA', +1479: 'HEBREW POINT QAMATS QATAN', 1488: 'HEBREW LETTER ALEF', 1489: 'HEBREW LETTER BET', 1490: 'HEBREW LETTER GIMEL', @@ -1301,8 +1366,23 @@ 1522: 'HEBREW LIGATURE YIDDISH DOUBLE YOD', 1523: 'HEBREW PUNCTUATION GERESH', 1524: 'HEBREW PUNCTUATION GERSHAYIM', +1536: 'ARABIC NUMBER SIGN', +1537: 'ARABIC SIGN SANAH', +1538: 'ARABIC FOOTNOTE MARKER', +1539: 'ARABIC SIGN SAFHA', +1547: 'AFGHANI SIGN', 1548: 'ARABIC COMMA', +1549: 'ARABIC DATE SEPARATOR', +1550: 'ARABIC POETIC VERSE SIGN', +1551: 'ARABIC SIGN MISRA', +1552: 'ARABIC SIGN SALLALLAHOU ALAYHE WASSALLAM', +1553: 'ARABIC SIGN ALAYHE ASSALLAM', +1554: 'ARABIC SIGN RAHMATULLAH ALAYHE', +1555: 'ARABIC SIGN RADI ALLAHOU ANHU', +1556: 'ARABIC SIGN TAKHALLUS', +1557: 'ARABIC SMALL HIGH TAH', 1563: 'ARABIC SEMICOLON', +1566: 'ARABIC TRIPLE DOT PUNCTUATION MARK', 1567: 'ARABIC QUESTION MARK', 1569: 'ARABIC LETTER HAMZA', 1570: 'ARABIC LETTER ALEF WITH MADDA ABOVE', @@ -1352,6 +1432,15 @@ 1619: 'ARABIC MADDAH ABOVE', 1620: 'ARABIC HAMZA ABOVE', 1621: 'ARABIC HAMZA BELOW', +1622: 'ARABIC SUBSCRIPT ALEF', +1623: 'ARABIC INVERTED DAMMA', +1624: 'ARABIC MARK NOON GHUNNA', +1625: 'ARABIC ZWARAKAY', +1626: 'ARABIC VOWEL SIGN SMALL V ABOVE', +1627: 'ARABIC VOWEL SIGN INVERTED SMALL V ABOVE', +1628: 'ARABIC VOWEL SIGN DOT BELOW', +1629: 'ARABIC REVERSED DAMMA', +1630: 'ARABIC FATHA WITH TWO DOTS', 1632: 'ARABIC-INDIC DIGIT ZERO', 1633: 'ARABIC-INDIC DIGIT ONE', 1634: 'ARABIC-INDIC DIGIT TWO', @@ -1494,6 +1583,8 @@ 1771: 'ARABIC EMPTY CENTRE HIGH STOP', 1772: 'ARABIC ROUNDED HIGH STOP WITH FILLED CENTRE', 1773: 'ARABIC SMALL LOW MEEM', +1774: 'ARABIC LETTER DAL WITH INVERTED V', +1775: 'ARABIC LETTER REH WITH INVERTED V', 1776: 'EXTENDED ARABIC-INDIC DIGIT ZERO', 1777: 'EXTENDED ARABIC-INDIC DIGIT ONE', 1778: 'EXTENDED ARABIC-INDIC DIGIT TWO', @@ -1509,6 +1600,7 @@ 1788: 'ARABIC LETTER GHAIN WITH DOT BELOW', 1789: 'ARABIC SIGN SINDHI AMPERSAND', 1790: 'ARABIC SIGN SINDHI POSTPOSITION MEN', +1791: 'ARABIC LETTER HEH WITH INVERTED V', 1792: 'SYRIAC END OF PARAGRAPH', 1793: 'SYRIAC SUPRALINEAR FULL STOP', 1794: 'SYRIAC SUBLINEAR FULL STOP', @@ -1553,6 +1645,9 @@ 1834: 'SYRIAC LETTER RISH', 1835: 'SYRIAC LETTER SHIN', 1836: 'SYRIAC LETTER TAW', +1837: 'SYRIAC LETTER PERSIAN BHETH', +1838: 'SYRIAC LETTER PERSIAN GHAMAL', +1839: 'SYRIAC LETTER PERSIAN DHALATH', 1840: 'SYRIAC PTHAHA ABOVE', 1841: 'SYRIAC PTHAHA BELOW', 1842: 'SYRIAC PTHAHA DOTTED', @@ -1580,6 +1675,39 @@ 1864: 'SYRIAC OBLIQUE LINE BELOW', 1865: 'SYRIAC MUSIC', 1866: 'SYRIAC BARREKH', +1869: 'SYRIAC LETTER SOGDIAN ZHAIN', +1870: 'SYRIAC LETTER SOGDIAN KHAPH', +1871: 'SYRIAC LETTER SOGDIAN FE', +1872: 'ARABIC LETTER BEH WITH THREE DOTS HORIZONTALLY BELOW', +1873: 'ARABIC LETTER BEH WITH DOT BELOW AND THREE DOTS ABOVE', +1874: 'ARABIC LETTER BEH WITH THREE DOTS POINTING UPWARDS BELOW', +1875: 'ARABIC LETTER BEH WITH THREE DOTS POINTING UPWARDS BELOW AND TWO DOTS ABOVE', +1876: 'ARABIC LETTER BEH WITH TWO DOTS BELOW AND DOT ABOVE', +1877: 'ARABIC LETTER BEH WITH INVERTED SMALL V BELOW', +1878: 'ARABIC LETTER BEH WITH SMALL V', +1879: 'ARABIC LETTER HAH WITH TWO DOTS ABOVE', +1880: 'ARABIC LETTER HAH WITH THREE DOTS POINTING UPWARDS BELOW', +1881: 'ARABIC LETTER DAL WITH TWO DOTS VERTICALLY BELOW AND SMALL TAH', +1882: 'ARABIC LETTER DAL WITH INVERTED SMALL V BELOW', +1883: 'ARABIC LETTER REH WITH STROKE', +1884: 'ARABIC LETTER SEEN WITH FOUR DOTS ABOVE', +1885: 'ARABIC LETTER AIN WITH TWO DOTS ABOVE', +1886: 'ARABIC LETTER AIN WITH THREE DOTS POINTING DOWNWARDS ABOVE', +1887: 'ARABIC LETTER AIN WITH TWO DOTS VERTICALLY ABOVE', +1888: 'ARABIC LETTER FEH WITH TWO DOTS BELOW', +1889: 'ARABIC LETTER FEH WITH THREE DOTS POINTING UPWARDS BELOW', +1890: 'ARABIC LETTER KEHEH WITH DOT ABOVE', +1891: 'ARABIC LETTER KEHEH WITH THREE DOTS ABOVE', +1892: 'ARABIC LETTER KEHEH WITH THREE DOTS POINTING UPWARDS BELOW', +1893: 'ARABIC LETTER MEEM WITH DOT ABOVE', +1894: 'ARABIC LETTER MEEM WITH DOT BELOW', +1895: 'ARABIC LETTER NOON WITH TWO DOTS BELOW', +1896: 'ARABIC LETTER NOON WITH SMALL TAH', +1897: 'ARABIC LETTER NOON WITH SMALL V', +1898: 'ARABIC LETTER LAM WITH BAR', +1899: 'ARABIC LETTER REH WITH TWO DOTS VERTICALLY ABOVE', +1900: 'ARABIC LETTER REH WITH HAMZA ABOVE', +1901: 'ARABIC LETTER SEEN WITH TWO DOTS VERTICALLY ABOVE', 1920: 'THAANA LETTER HAA', 1921: 'THAANA LETTER SHAVIYANI', 1922: 'THAANA LETTER NOONU', @@ -1633,6 +1761,7 @@ 2305: 'DEVANAGARI SIGN CANDRABINDU', 2306: 'DEVANAGARI SIGN ANUSVARA', 2307: 'DEVANAGARI SIGN VISARGA', +2308: 'DEVANAGARI LETTER SHORT A', 2309: 'DEVANAGARI LETTER A', 2310: 'DEVANAGARI LETTER AA', 2311: 'DEVANAGARI LETTER I', @@ -1734,6 +1863,7 @@ 2414: 'DEVANAGARI DIGIT EIGHT', 2415: 'DEVANAGARI DIGIT NINE', 2416: 'DEVANAGARI ABBREVIATION SIGN', +2429: 'DEVANAGARI LETTER GLOTTAL STOP', 2433: 'BENGALI SIGN CANDRABINDU', 2434: 'BENGALI SIGN ANUSVARA', 2435: 'BENGALI SIGN VISARGA', @@ -1782,6 +1912,7 @@ 2488: 'BENGALI LETTER SA', 2489: 'BENGALI LETTER HA', 2492: 'BENGALI SIGN NUKTA', +2493: 'BENGALI SIGN AVAGRAHA', 2494: 'BENGALI VOWEL SIGN AA', 2495: 'BENGALI VOWEL SIGN I', 2496: 'BENGALI VOWEL SIGN II', @@ -1794,6 +1925,7 @@ 2507: 'BENGALI VOWEL SIGN O', 2508: 'BENGALI VOWEL SIGN AU', 2509: 'BENGALI SIGN VIRAMA', +2510: 'BENGALI LETTER KHANDA TA', 2519: 'BENGALI AU LENGTH MARK', 2524: 'BENGALI LETTER RRA', 2525: 'BENGALI LETTER RHA', @@ -1823,7 +1955,9 @@ 2552: 'BENGALI CURRENCY NUMERATOR ONE LESS THAN THE DENOMINATOR', 2553: 'BENGALI CURRENCY DENOMINATOR SIXTEEN', 2554: 'BENGALI ISSHAR', +2561: 'GURMUKHI SIGN ADAK BINDI', 2562: 'GURMUKHI SIGN BINDI', +2563: 'GURMUKHI SIGN VISARGA', 2565: 'GURMUKHI LETTER A', 2566: 'GURMUKHI LETTER AA', 2567: 'GURMUKHI LETTER I', @@ -1908,6 +2042,7 @@ 2697: 'GUJARATI LETTER U', 2698: 'GUJARATI LETTER UU', 2699: 'GUJARATI LETTER VOCALIC R', +2700: 'GUJARATI LETTER VOCALIC L', 2701: 'GUJARATI VOWEL CANDRA E', 2703: 'GUJARATI LETTER E', 2704: 'GUJARATI LETTER AI', @@ -1966,6 +2101,9 @@ 2765: 'GUJARATI SIGN VIRAMA', 2768: 'GUJARATI OM', 2784: 'GUJARATI LETTER VOCALIC RR', +2785: 'GUJARATI LETTER VOCALIC LL', +2786: 'GUJARATI VOWEL SIGN VOCALIC L', +2787: 'GUJARATI VOWEL SIGN VOCALIC LL', 2790: 'GUJARATI DIGIT ZERO', 2791: 'GUJARATI DIGIT ONE', 2792: 'GUJARATI DIGIT TWO', @@ -1976,6 +2114,7 @@ 2797: 'GUJARATI DIGIT SEVEN', 2798: 'GUJARATI DIGIT EIGHT', 2799: 'GUJARATI DIGIT NINE', +2801: 'GUJARATI RUPEE SIGN', 2817: 'ORIYA SIGN CANDRABINDU', 2818: 'ORIYA SIGN ANUSVARA', 2819: 'ORIYA SIGN VISARGA', @@ -2020,6 +2159,7 @@ 2864: 'ORIYA LETTER RA', 2866: 'ORIYA LETTER LA', 2867: 'ORIYA LETTER LLA', +2869: 'ORIYA LETTER VA', 2870: 'ORIYA LETTER SHA', 2871: 'ORIYA LETTER SSA', 2872: 'ORIYA LETTER SA', @@ -2055,6 +2195,7 @@ 2926: 'ORIYA DIGIT EIGHT', 2927: 'ORIYA DIGIT NINE', 2928: 'ORIYA ISSHAR', +2929: 'ORIYA LETTER WA', 2946: 'TAMIL SIGN ANUSVARA', 2947: 'TAMIL SIGN VISARGA', 2949: 'TAMIL LETTER A', @@ -2088,6 +2229,7 @@ 2995: 'TAMIL LETTER LLA', 2996: 'TAMIL LETTER LLLA', 2997: 'TAMIL LETTER VA', +2998: 'TAMIL LETTER SHA', 2999: 'TAMIL LETTER SSA', 3000: 'TAMIL LETTER SA', 3001: 'TAMIL LETTER HA', @@ -2104,6 +2246,7 @@ 3020: 'TAMIL VOWEL SIGN AU', 3021: 'TAMIL SIGN VIRAMA', 3031: 'TAMIL AU LENGTH MARK', +3046: 'TAMIL DIGIT ZERO', 3047: 'TAMIL DIGIT ONE', 3048: 'TAMIL DIGIT TWO', 3049: 'TAMIL DIGIT THREE', @@ -2116,6 +2259,14 @@ 3056: 'TAMIL NUMBER TEN', 3057: 'TAMIL NUMBER ONE HUNDRED', 3058: 'TAMIL NUMBER ONE THOUSAND', +3059: 'TAMIL DAY SIGN', +3060: 'TAMIL MONTH SIGN', +3061: 'TAMIL YEAR SIGN', +3062: 'TAMIL DEBIT SIGN', +3063: 'TAMIL CREDIT SIGN', +3064: 'TAMIL AS ABOVE SIGN', +3065: 'TAMIL RUPEE SIGN', +3066: 'TAMIL NUMBER SIGN', 3073: 'TELUGU SIGN CANDRABINDU', 3074: 'TELUGU SIGN ANUSVARA', 3075: 'TELUGU SIGN VISARGA', @@ -2247,6 +2398,8 @@ 3255: 'KANNADA LETTER SSA', 3256: 'KANNADA LETTER SA', 3257: 'KANNADA LETTER HA', +3260: 'KANNADA SIGN NUKTA', +3261: 'KANNADA SIGN AVAGRAHA', 3262: 'KANNADA VOWEL SIGN AA', 3263: 'KANNADA VOWEL SIGN I', 3264: 'KANNADA VOWEL SIGN II', @@ -2779,6 +2932,8 @@ 4043: 'TIBETAN SYMBOL NOR BU GSUM -KHYIL', 4044: 'TIBETAN SYMBOL NOR BU BZHI -KHYIL', 4047: 'TIBETAN SIGN RDEL NAG GSUM', +4048: 'TIBETAN MARK BSKA- SHOG GI MGO RGYAN', +4049: 'TIBETAN MARK MNYAM YIG GI MGO RGYAN', 4096: 'MYANMAR LETTER KA', 4097: 'MYANMAR LETTER KHA', 4098: 'MYANMAR LETTER GA', @@ -2936,7 +3091,10 @@ 4342: 'GEORGIAN LETTER FI', 4343: 'GEORGIAN LETTER YN', 4344: 'GEORGIAN LETTER ELIFI', +4345: 'GEORGIAN LETTER TURNED GAN', +4346: 'GEORGIAN LETTER AIN', 4347: 'GEORGIAN PARAGRAPH SEPARATOR', +4348: 'MODIFIER LETTER GEORGIAN NAR', 4352: 'HANGUL CHOSEONG KIYEOK', 4353: 'HANGUL CHOSEONG SSANGKIYEOK', 4354: 'HANGUL CHOSEONG NIEUN', @@ -3184,6 +3342,7 @@ 4612: 'ETHIOPIC SYLLABLE HEE', 4613: 'ETHIOPIC SYLLABLE HE', 4614: 'ETHIOPIC SYLLABLE HO', +4615: 'ETHIOPIC SYLLABLE HOA', 4616: 'ETHIOPIC SYLLABLE LA', 4617: 'ETHIOPIC SYLLABLE LU', 4618: 'ETHIOPIC SYLLABLE LI', @@ -3247,6 +3406,7 @@ 4676: 'ETHIOPIC SYLLABLE QEE', 4677: 'ETHIOPIC SYLLABLE QE', 4678: 'ETHIOPIC SYLLABLE QO', +4679: 'ETHIOPIC SYLLABLE QOA', 4680: 'ETHIOPIC SYLLABLE QWA', 4682: 'ETHIOPIC SYLLABLE QWI', 4683: 'ETHIOPIC SYLLABLE QWAA', @@ -3303,6 +3463,7 @@ 4740: 'ETHIOPIC SYLLABLE XEE', 4741: 'ETHIOPIC SYLLABLE XE', 4742: 'ETHIOPIC SYLLABLE XO', +4743: 'ETHIOPIC SYLLABLE XOA', 4744: 'ETHIOPIC SYLLABLE XWA', 4746: 'ETHIOPIC SYLLABLE XWI', 4747: 'ETHIOPIC SYLLABLE XWAA', @@ -3339,6 +3500,7 @@ 4780: 'ETHIOPIC SYLLABLE KEE', 4781: 'ETHIOPIC SYLLABLE KE', 4782: 'ETHIOPIC SYLLABLE KO', +4783: 'ETHIOPIC SYLLABLE KOA', 4784: 'ETHIOPIC SYLLABLE KWA', 4786: 'ETHIOPIC SYLLABLE KWI', 4787: 'ETHIOPIC SYLLABLE KWAA', @@ -3363,6 +3525,7 @@ 4812: 'ETHIOPIC SYLLABLE WEE', 4813: 'ETHIOPIC SYLLABLE WE', 4814: 'ETHIOPIC SYLLABLE WO', +4815: 'ETHIOPIC SYLLABLE WOA', 4816: 'ETHIOPIC SYLLABLE PHARYNGEAL A', 4817: 'ETHIOPIC SYLLABLE PHARYNGEAL U', 4818: 'ETHIOPIC SYLLABLE PHARYNGEAL I', @@ -3393,6 +3556,7 @@ 4844: 'ETHIOPIC SYLLABLE YEE', 4845: 'ETHIOPIC SYLLABLE YE', 4846: 'ETHIOPIC SYLLABLE YO', +4847: 'ETHIOPIC SYLLABLE YOA', 4848: 'ETHIOPIC SYLLABLE DA', 4849: 'ETHIOPIC SYLLABLE DU', 4850: 'ETHIOPIC SYLLABLE DI', @@ -3424,6 +3588,7 @@ 4876: 'ETHIOPIC SYLLABLE GEE', 4877: 'ETHIOPIC SYLLABLE GE', 4878: 'ETHIOPIC SYLLABLE GO', +4879: 'ETHIOPIC SYLLABLE GOA', 4880: 'ETHIOPIC SYLLABLE GWA', 4882: 'ETHIOPIC SYLLABLE GWI', 4883: 'ETHIOPIC SYLLABLE GWAA', @@ -3436,6 +3601,7 @@ 4892: 'ETHIOPIC SYLLABLE GGEE', 4893: 'ETHIOPIC SYLLABLE GGE', 4894: 'ETHIOPIC SYLLABLE GGO', +4895: 'ETHIOPIC SYLLABLE GGWAA', 4896: 'ETHIOPIC SYLLABLE THA', 4897: 'ETHIOPIC SYLLABLE THU', 4898: 'ETHIOPIC SYLLABLE THI', @@ -3475,6 +3641,7 @@ 4932: 'ETHIOPIC SYLLABLE TZEE', 4933: 'ETHIOPIC SYLLABLE TZE', 4934: 'ETHIOPIC SYLLABLE TZO', +4935: 'ETHIOPIC SYLLABLE TZOA', 4936: 'ETHIOPIC SYLLABLE FA', 4937: 'ETHIOPIC SYLLABLE FU', 4938: 'ETHIOPIC SYLLABLE FI', @@ -3494,6 +3661,8 @@ 4952: 'ETHIOPIC SYLLABLE RYA', 4953: 'ETHIOPIC SYLLABLE MYA', 4954: 'ETHIOPIC SYLLABLE FYA', +4959: 'ETHIOPIC COMBINING GEMINATION MARK', +4960: 'ETHIOPIC SECTION MARK', 4961: 'ETHIOPIC WORDSPACE', 4962: 'ETHIOPIC FULL STOP', 4963: 'ETHIOPIC COMMA', @@ -3522,6 +3691,32 @@ 4986: 'ETHIOPIC NUMBER NINETY', 4987: 'ETHIOPIC NUMBER HUNDRED', 4988: 'ETHIOPIC NUMBER TEN THOUSAND', +4992: 'ETHIOPIC SYLLABLE SEBATBEIT MWA', +4993: 'ETHIOPIC SYLLABLE MWI', +4994: 'ETHIOPIC SYLLABLE MWEE', +4995: 'ETHIOPIC SYLLABLE MWE', +4996: 'ETHIOPIC SYLLABLE SEBATBEIT BWA', +4997: 'ETHIOPIC SYLLABLE BWI', +4998: 'ETHIOPIC SYLLABLE BWEE', +4999: 'ETHIOPIC SYLLABLE BWE', +5000: 'ETHIOPIC SYLLABLE SEBATBEIT FWA', +5001: 'ETHIOPIC SYLLABLE FWI', +5002: 'ETHIOPIC SYLLABLE FWEE', +5003: 'ETHIOPIC SYLLABLE FWE', +5004: 'ETHIOPIC SYLLABLE SEBATBEIT PWA', +5005: 'ETHIOPIC SYLLABLE PWI', +5006: 'ETHIOPIC SYLLABLE PWEE', +5007: 'ETHIOPIC SYLLABLE PWE', +5008: 'ETHIOPIC TONAL MARK YIZET', +5009: 'ETHIOPIC TONAL MARK DERET', +5010: 'ETHIOPIC TONAL MARK RIKRIK', +5011: 'ETHIOPIC TONAL MARK SHORT RIKRIK', +5012: 'ETHIOPIC TONAL MARK DIFAT', +5013: 'ETHIOPIC TONAL MARK KENAT', +5014: 'ETHIOPIC TONAL MARK CHIRET', +5015: 'ETHIOPIC TONAL MARK HIDET', +5016: 'ETHIOPIC TONAL MARK DERET-HIDET', +5017: 'ETHIOPIC TONAL MARK KURT', 5024: 'CHEROKEE LETTER A', 5025: 'CHEROKEE LETTER E', 5026: 'CHEROKEE LETTER I', @@ -4521,6 +4716,7 @@ 6106: 'KHMER SIGN KOOMUUT', 6107: 'KHMER CURRENCY SYMBOL RIEL', 6108: 'KHMER SIGN AVAKRAHASANYA', +6109: 'KHMER SIGN ATTHACAN', 6112: 'KHMER DIGIT ZERO', 6113: 'KHMER DIGIT ONE', 6114: 'KHMER DIGIT TWO', @@ -4531,6 +4727,16 @@ 6119: 'KHMER DIGIT SEVEN', 6120: 'KHMER DIGIT EIGHT', 6121: 'KHMER DIGIT NINE', +6128: 'KHMER SYMBOL LEK ATTAK SON', +6129: 'KHMER SYMBOL LEK ATTAK MUOY', +6130: 'KHMER SYMBOL LEK ATTAK PII', +6131: 'KHMER SYMBOL LEK ATTAK BEI', +6132: 'KHMER SYMBOL LEK ATTAK BUON', +6133: 'KHMER SYMBOL LEK ATTAK PRAM', +6134: 'KHMER SYMBOL LEK ATTAK PRAM-MUOY', +6135: 'KHMER SYMBOL LEK ATTAK PRAM-PII', +6136: 'KHMER SYMBOL LEK ATTAK PRAM-BEI', +6137: 'KHMER SYMBOL LEK ATTAK PRAM-BUON', 6144: 'MONGOLIAN BIRGA', 6145: 'MONGOLIAN ELLIPSIS', 6146: 'MONGOLIAN COMMA', @@ -4686,6 +4892,445 @@ 6311: 'MONGOLIAN LETTER ALI GALI HALF YA', 6312: 'MONGOLIAN LETTER MANCHU ALI GALI BHA', 6313: 'MONGOLIAN LETTER ALI GALI DAGALGA', +6400: 'LIMBU VOWEL-CARRIER LETTER', +6401: 'LIMBU LETTER KA', +6402: 'LIMBU LETTER KHA', +6403: 'LIMBU LETTER GA', +6404: 'LIMBU LETTER GHA', +6405: 'LIMBU LETTER NGA', +6406: 'LIMBU LETTER CA', +6407: 'LIMBU LETTER CHA', +6408: 'LIMBU LETTER JA', +6409: 'LIMBU LETTER JHA', +6410: 'LIMBU LETTER YAN', +6411: 'LIMBU LETTER TA', +6412: 'LIMBU LETTER THA', +6413: 'LIMBU LETTER DA', +6414: 'LIMBU LETTER DHA', +6415: 'LIMBU LETTER NA', +6416: 'LIMBU LETTER PA', +6417: 'LIMBU LETTER PHA', +6418: 'LIMBU LETTER BA', +6419: 'LIMBU LETTER BHA', +6420: 'LIMBU LETTER MA', +6421: 'LIMBU LETTER YA', +6422: 'LIMBU LETTER RA', +6423: 'LIMBU LETTER LA', +6424: 'LIMBU LETTER WA', +6425: 'LIMBU LETTER SHA', +6426: 'LIMBU LETTER SSA', +6427: 'LIMBU LETTER SA', +6428: 'LIMBU LETTER HA', +6432: 'LIMBU VOWEL SIGN A', +6433: 'LIMBU VOWEL SIGN I', +6434: 'LIMBU VOWEL SIGN U', +6435: 'LIMBU VOWEL SIGN EE', +6436: 'LIMBU VOWEL SIGN AI', +6437: 'LIMBU VOWEL SIGN OO', +6438: 'LIMBU VOWEL SIGN AU', +6439: 'LIMBU VOWEL SIGN E', +6440: 'LIMBU VOWEL SIGN O', +6441: 'LIMBU SUBJOINED LETTER YA', +6442: 'LIMBU SUBJOINED LETTER RA', +6443: 'LIMBU SUBJOINED LETTER WA', +6448: 'LIMBU SMALL LETTER KA', +6449: 'LIMBU SMALL LETTER NGA', +6450: 'LIMBU SMALL LETTER ANUSVARA', +6451: 'LIMBU SMALL LETTER TA', +6452: 'LIMBU SMALL LETTER NA', +6453: 'LIMBU SMALL LETTER PA', +6454: 'LIMBU SMALL LETTER MA', +6455: 'LIMBU SMALL LETTER RA', +6456: 'LIMBU SMALL LETTER LA', +6457: 'LIMBU SIGN MUKPHRENG', +6458: 'LIMBU SIGN KEMPHRENG', +6459: 'LIMBU SIGN SA-I', +6464: 'LIMBU SIGN LOO', +6468: 'LIMBU EXCLAMATION MARK', +6469: 'LIMBU QUESTION MARK', +6470: 'LIMBU DIGIT ZERO', +6471: 'LIMBU DIGIT ONE', +6472: 'LIMBU DIGIT TWO', +6473: 'LIMBU DIGIT THREE', +6474: 'LIMBU DIGIT FOUR', +6475: 'LIMBU DIGIT FIVE', +6476: 'LIMBU DIGIT SIX', +6477: 'LIMBU DIGIT SEVEN', +6478: 'LIMBU DIGIT EIGHT', +6479: 'LIMBU DIGIT NINE', +6480: 'TAI LE LETTER KA', +6481: 'TAI LE LETTER XA', +6482: 'TAI LE LETTER NGA', +6483: 'TAI LE LETTER TSA', +6484: 'TAI LE LETTER SA', +6485: 'TAI LE LETTER YA', +6486: 'TAI LE LETTER TA', +6487: 'TAI LE LETTER THA', +6488: 'TAI LE LETTER LA', +6489: 'TAI LE LETTER PA', +6490: 'TAI LE LETTER PHA', +6491: 'TAI LE LETTER MA', +6492: 'TAI LE LETTER FA', +6493: 'TAI LE LETTER VA', +6494: 'TAI LE LETTER HA', +6495: 'TAI LE LETTER QA', +6496: 'TAI LE LETTER KHA', +6497: 'TAI LE LETTER TSHA', +6498: 'TAI LE LETTER NA', +6499: 'TAI LE LETTER A', +6500: 'TAI LE LETTER I', +6501: 'TAI LE LETTER EE', +6502: 'TAI LE LETTER EH', +6503: 'TAI LE LETTER U', +6504: 'TAI LE LETTER OO', +6505: 'TAI LE LETTER O', +6506: 'TAI LE LETTER UE', +6507: 'TAI LE LETTER E', +6508: 'TAI LE LETTER AUE', +6509: 'TAI LE LETTER AI', +6512: 'TAI LE LETTER TONE-2', +6513: 'TAI LE LETTER TONE-3', +6514: 'TAI LE LETTER TONE-4', +6515: 'TAI LE LETTER TONE-5', +6516: 'TAI LE LETTER TONE-6', +6528: 'NEW TAI LUE LETTER HIGH QA', +6529: 'NEW TAI LUE LETTER LOW QA', +6530: 'NEW TAI LUE LETTER HIGH KA', +6531: 'NEW TAI LUE LETTER HIGH XA', +6532: 'NEW TAI LUE LETTER HIGH NGA', +6533: 'NEW TAI LUE LETTER LOW KA', +6534: 'NEW TAI LUE LETTER LOW XA', +6535: 'NEW TAI LUE LETTER LOW NGA', +6536: 'NEW TAI LUE LETTER HIGH TSA', +6537: 'NEW TAI LUE LETTER HIGH SA', +6538: 'NEW TAI LUE LETTER HIGH YA', +6539: 'NEW TAI LUE LETTER LOW TSA', +6540: 'NEW TAI LUE LETTER LOW SA', +6541: 'NEW TAI LUE LETTER LOW YA', +6542: 'NEW TAI LUE LETTER HIGH TA', +6543: 'NEW TAI LUE LETTER HIGH THA', +6544: 'NEW TAI LUE LETTER HIGH NA', +6545: 'NEW TAI LUE LETTER LOW TA', +6546: 'NEW TAI LUE LETTER LOW THA', +6547: 'NEW TAI LUE LETTER LOW NA', +6548: 'NEW TAI LUE LETTER HIGH PA', +6549: 'NEW TAI LUE LETTER HIGH PHA', +6550: 'NEW TAI LUE LETTER HIGH MA', +6551: 'NEW TAI LUE LETTER LOW PA', +6552: 'NEW TAI LUE LETTER LOW PHA', +6553: 'NEW TAI LUE LETTER LOW MA', +6554: 'NEW TAI LUE LETTER HIGH FA', +6555: 'NEW TAI LUE LETTER HIGH VA', +6556: 'NEW TAI LUE LETTER HIGH LA', +6557: 'NEW TAI LUE LETTER LOW FA', +6558: 'NEW TAI LUE LETTER LOW VA', +6559: 'NEW TAI LUE LETTER LOW LA', +6560: 'NEW TAI LUE LETTER HIGH HA', +6561: 'NEW TAI LUE LETTER HIGH DA', +6562: 'NEW TAI LUE LETTER HIGH BA', +6563: 'NEW TAI LUE LETTER LOW HA', +6564: 'NEW TAI LUE LETTER LOW DA', +6565: 'NEW TAI LUE LETTER LOW BA', +6566: 'NEW TAI LUE LETTER HIGH KVA', +6567: 'NEW TAI LUE LETTER HIGH XVA', +6568: 'NEW TAI LUE LETTER LOW KVA', +6569: 'NEW TAI LUE LETTER LOW XVA', +6576: 'NEW TAI LUE VOWEL SIGN VOWEL SHORTENER', +6577: 'NEW TAI LUE VOWEL SIGN AA', +6578: 'NEW TAI LUE VOWEL SIGN II', +6579: 'NEW TAI LUE VOWEL SIGN U', +6580: 'NEW TAI LUE VOWEL SIGN UU', +6581: 'NEW TAI LUE VOWEL SIGN E', +6582: 'NEW TAI LUE VOWEL SIGN AE', +6583: 'NEW TAI LUE VOWEL SIGN O', +6584: 'NEW TAI LUE VOWEL SIGN OA', +6585: 'NEW TAI LUE VOWEL SIGN UE', +6586: 'NEW TAI LUE VOWEL SIGN AY', +6587: 'NEW TAI LUE VOWEL SIGN AAY', +6588: 'NEW TAI LUE VOWEL SIGN UY', +6589: 'NEW TAI LUE VOWEL SIGN OY', +6590: 'NEW TAI LUE VOWEL SIGN OAY', +6591: 'NEW TAI LUE VOWEL SIGN UEY', +6592: 'NEW TAI LUE VOWEL SIGN IY', +6593: 'NEW TAI LUE LETTER FINAL V', +6594: 'NEW TAI LUE LETTER FINAL NG', +6595: 'NEW TAI LUE LETTER FINAL N', +6596: 'NEW TAI LUE LETTER FINAL M', +6597: 'NEW TAI LUE LETTER FINAL K', +6598: 'NEW TAI LUE LETTER FINAL D', +6599: 'NEW TAI LUE LETTER FINAL B', +6600: 'NEW TAI LUE TONE MARK-1', +6601: 'NEW TAI LUE TONE MARK-2', +6608: 'NEW TAI LUE DIGIT ZERO', +6609: 'NEW TAI LUE DIGIT ONE', +6610: 'NEW TAI LUE DIGIT TWO', +6611: 'NEW TAI LUE DIGIT THREE', +6612: 'NEW TAI LUE DIGIT FOUR', +6613: 'NEW TAI LUE DIGIT FIVE', +6614: 'NEW TAI LUE DIGIT SIX', +6615: 'NEW TAI LUE DIGIT SEVEN', +6616: 'NEW TAI LUE DIGIT EIGHT', +6617: 'NEW TAI LUE DIGIT NINE', +6622: 'NEW TAI LUE SIGN LAE', +6623: 'NEW TAI LUE SIGN LAEV', +6624: 'KHMER SYMBOL PATHAMASAT', +6625: 'KHMER SYMBOL MUOY KOET', +6626: 'KHMER SYMBOL PII KOET', +6627: 'KHMER SYMBOL BEI KOET', +6628: 'KHMER SYMBOL BUON KOET', +6629: 'KHMER SYMBOL PRAM KOET', +6630: 'KHMER SYMBOL PRAM-MUOY KOET', +6631: 'KHMER SYMBOL PRAM-PII KOET', +6632: 'KHMER SYMBOL PRAM-BEI KOET', +6633: 'KHMER SYMBOL PRAM-BUON KOET', +6634: 'KHMER SYMBOL DAP KOET', +6635: 'KHMER SYMBOL DAP-MUOY KOET', +6636: 'KHMER SYMBOL DAP-PII KOET', +6637: 'KHMER SYMBOL DAP-BEI KOET', +6638: 'KHMER SYMBOL DAP-BUON KOET', +6639: 'KHMER SYMBOL DAP-PRAM KOET', +6640: 'KHMER SYMBOL TUTEYASAT', +6641: 'KHMER SYMBOL MUOY ROC', +6642: 'KHMER SYMBOL PII ROC', +6643: 'KHMER SYMBOL BEI ROC', +6644: 'KHMER SYMBOL BUON ROC', +6645: 'KHMER SYMBOL PRAM ROC', +6646: 'KHMER SYMBOL PRAM-MUOY ROC', +6647: 'KHMER SYMBOL PRAM-PII ROC', +6648: 'KHMER SYMBOL PRAM-BEI ROC', +6649: 'KHMER SYMBOL PRAM-BUON ROC', +6650: 'KHMER SYMBOL DAP ROC', +6651: 'KHMER SYMBOL DAP-MUOY ROC', +6652: 'KHMER SYMBOL DAP-PII ROC', +6653: 'KHMER SYMBOL DAP-BEI ROC', +6654: 'KHMER SYMBOL DAP-BUON ROC', +6655: 'KHMER SYMBOL DAP-PRAM ROC', +6656: 'BUGINESE LETTER KA', +6657: 'BUGINESE LETTER GA', +6658: 'BUGINESE LETTER NGA', +6659: 'BUGINESE LETTER NGKA', +6660: 'BUGINESE LETTER PA', +6661: 'BUGINESE LETTER BA', +6662: 'BUGINESE LETTER MA', +6663: 'BUGINESE LETTER MPA', +6664: 'BUGINESE LETTER TA', +6665: 'BUGINESE LETTER DA', +6666: 'BUGINESE LETTER NA', +6667: 'BUGINESE LETTER NRA', +6668: 'BUGINESE LETTER CA', +6669: 'BUGINESE LETTER JA', +6670: 'BUGINESE LETTER NYA', +6671: 'BUGINESE LETTER NYCA', +6672: 'BUGINESE LETTER YA', +6673: 'BUGINESE LETTER RA', +6674: 'BUGINESE LETTER LA', +6675: 'BUGINESE LETTER VA', +6676: 'BUGINESE LETTER SA', +6677: 'BUGINESE LETTER A', +6678: 'BUGINESE LETTER HA', +6679: 'BUGINESE VOWEL SIGN I', +6680: 'BUGINESE VOWEL SIGN U', +6681: 'BUGINESE VOWEL SIGN E', +6682: 'BUGINESE VOWEL SIGN O', +6683: 'BUGINESE VOWEL SIGN AE', +6686: 'BUGINESE PALLAWA', +6687: 'BUGINESE END OF SECTION', +7424: 'LATIN LETTER SMALL CAPITAL A', +7425: 'LATIN LETTER SMALL CAPITAL AE', +7426: 'LATIN SMALL LETTER TURNED AE', +7427: 'LATIN LETTER SMALL CAPITAL BARRED B', +7428: 'LATIN LETTER SMALL CAPITAL C', +7429: 'LATIN LETTER SMALL CAPITAL D', +7430: 'LATIN LETTER SMALL CAPITAL ETH', +7431: 'LATIN LETTER SMALL CAPITAL E', +7432: 'LATIN SMALL LETTER TURNED OPEN E', +7433: 'LATIN SMALL LETTER TURNED I', +7434: 'LATIN LETTER SMALL CAPITAL J', +7435: 'LATIN LETTER SMALL CAPITAL K', +7436: 'LATIN LETTER SMALL CAPITAL L WITH STROKE', +7437: 'LATIN LETTER SMALL CAPITAL M', +7438: 'LATIN LETTER SMALL CAPITAL REVERSED N', +7439: 'LATIN LETTER SMALL CAPITAL O', +7440: 'LATIN LETTER SMALL CAPITAL OPEN O', +7441: 'LATIN SMALL LETTER SIDEWAYS O', +7442: 'LATIN SMALL LETTER SIDEWAYS OPEN O', +7443: 'LATIN SMALL LETTER SIDEWAYS O WITH STROKE', +7444: 'LATIN SMALL LETTER TURNED OE', +7445: 'LATIN LETTER SMALL CAPITAL OU', +7446: 'LATIN SMALL LETTER TOP HALF O', +7447: 'LATIN SMALL LETTER BOTTOM HALF O', +7448: 'LATIN LETTER SMALL CAPITAL P', +7449: 'LATIN LETTER SMALL CAPITAL REVERSED R', +7450: 'LATIN LETTER SMALL CAPITAL TURNED R', +7451: 'LATIN LETTER SMALL CAPITAL T', +7452: 'LATIN LETTER SMALL CAPITAL U', +7453: 'LATIN SMALL LETTER SIDEWAYS U', +7454: 'LATIN SMALL LETTER SIDEWAYS DIAERESIZED U', +7455: 'LATIN SMALL LETTER SIDEWAYS TURNED M', +7456: 'LATIN LETTER SMALL CAPITAL V', +7457: 'LATIN LETTER SMALL CAPITAL W', +7458: 'LATIN LETTER SMALL CAPITAL Z', +7459: 'LATIN LETTER SMALL CAPITAL EZH', +7460: 'LATIN LETTER VOICED LARYNGEAL SPIRANT', +7461: 'LATIN LETTER AIN', +7462: 'GREEK LETTER SMALL CAPITAL GAMMA', +7463: 'GREEK LETTER SMALL CAPITAL LAMDA', +7464: 'GREEK LETTER SMALL CAPITAL PI', +7465: 'GREEK LETTER SMALL CAPITAL RHO', +7466: 'GREEK LETTER SMALL CAPITAL PSI', +7467: 'CYRILLIC LETTER SMALL CAPITAL EL', +7468: 'MODIFIER LETTER CAPITAL A', +7469: 'MODIFIER LETTER CAPITAL AE', +7470: 'MODIFIER LETTER CAPITAL B', +7471: 'MODIFIER LETTER CAPITAL BARRED B', +7472: 'MODIFIER LETTER CAPITAL D', +7473: 'MODIFIER LETTER CAPITAL E', +7474: 'MODIFIER LETTER CAPITAL REVERSED E', +7475: 'MODIFIER LETTER CAPITAL G', +7476: 'MODIFIER LETTER CAPITAL H', +7477: 'MODIFIER LETTER CAPITAL I', +7478: 'MODIFIER LETTER CAPITAL J', +7479: 'MODIFIER LETTER CAPITAL K', +7480: 'MODIFIER LETTER CAPITAL L', +7481: 'MODIFIER LETTER CAPITAL M', +7482: 'MODIFIER LETTER CAPITAL N', +7483: 'MODIFIER LETTER CAPITAL REVERSED N', +7484: 'MODIFIER LETTER CAPITAL O', +7485: 'MODIFIER LETTER CAPITAL OU', +7486: 'MODIFIER LETTER CAPITAL P', +7487: 'MODIFIER LETTER CAPITAL R', +7488: 'MODIFIER LETTER CAPITAL T', +7489: 'MODIFIER LETTER CAPITAL U', +7490: 'MODIFIER LETTER CAPITAL W', +7491: 'MODIFIER LETTER SMALL A', +7492: 'MODIFIER LETTER SMALL TURNED A', +7493: 'MODIFIER LETTER SMALL ALPHA', +7494: 'MODIFIER LETTER SMALL TURNED AE', +7495: 'MODIFIER LETTER SMALL B', +7496: 'MODIFIER LETTER SMALL D', +7497: 'MODIFIER LETTER SMALL E', +7498: 'MODIFIER LETTER SMALL SCHWA', +7499: 'MODIFIER LETTER SMALL OPEN E', +7500: 'MODIFIER LETTER SMALL TURNED OPEN E', +7501: 'MODIFIER LETTER SMALL G', +7502: 'MODIFIER LETTER SMALL TURNED I', +7503: 'MODIFIER LETTER SMALL K', +7504: 'MODIFIER LETTER SMALL M', +7505: 'MODIFIER LETTER SMALL ENG', +7506: 'MODIFIER LETTER SMALL O', +7507: 'MODIFIER LETTER SMALL OPEN O', +7508: 'MODIFIER LETTER SMALL TOP HALF O', +7509: 'MODIFIER LETTER SMALL BOTTOM HALF O', +7510: 'MODIFIER LETTER SMALL P', +7511: 'MODIFIER LETTER SMALL T', +7512: 'MODIFIER LETTER SMALL U', +7513: 'MODIFIER LETTER SMALL SIDEWAYS U', +7514: 'MODIFIER LETTER SMALL TURNED M', +7515: 'MODIFIER LETTER SMALL V', +7516: 'MODIFIER LETTER SMALL AIN', +7517: 'MODIFIER LETTER SMALL BETA', +7518: 'MODIFIER LETTER SMALL GREEK GAMMA', +7519: 'MODIFIER LETTER SMALL DELTA', +7520: 'MODIFIER LETTER SMALL GREEK PHI', +7521: 'MODIFIER LETTER SMALL CHI', +7522: 'LATIN SUBSCRIPT SMALL LETTER I', +7523: 'LATIN SUBSCRIPT SMALL LETTER R', +7524: 'LATIN SUBSCRIPT SMALL LETTER U', +7525: 'LATIN SUBSCRIPT SMALL LETTER V', +7526: 'GREEK SUBSCRIPT SMALL LETTER BETA', +7527: 'GREEK SUBSCRIPT SMALL LETTER GAMMA', +7528: 'GREEK SUBSCRIPT SMALL LETTER RHO', +7529: 'GREEK SUBSCRIPT SMALL LETTER PHI', +7530: 'GREEK SUBSCRIPT SMALL LETTER CHI', +7531: 'LATIN SMALL LETTER UE', +7532: 'LATIN SMALL LETTER B WITH MIDDLE TILDE', +7533: 'LATIN SMALL LETTER D WITH MIDDLE TILDE', +7534: 'LATIN SMALL LETTER F WITH MIDDLE TILDE', +7535: 'LATIN SMALL LETTER M WITH MIDDLE TILDE', +7536: 'LATIN SMALL LETTER N WITH MIDDLE TILDE', +7537: 'LATIN SMALL LETTER P WITH MIDDLE TILDE', +7538: 'LATIN SMALL LETTER R WITH MIDDLE TILDE', +7539: 'LATIN SMALL LETTER R WITH FISHHOOK AND MIDDLE TILDE', +7540: 'LATIN SMALL LETTER S WITH MIDDLE TILDE', +7541: 'LATIN SMALL LETTER T WITH MIDDLE TILDE', +7542: 'LATIN SMALL LETTER Z WITH MIDDLE TILDE', +7543: 'LATIN SMALL LETTER TURNED G', +7544: 'MODIFIER LETTER CYRILLIC EN', +7545: 'LATIN SMALL LETTER INSULAR G', +7546: 'LATIN SMALL LETTER TH WITH STRIKETHROUGH', +7547: 'LATIN SMALL CAPITAL LETTER I WITH STROKE', +7548: 'LATIN SMALL LETTER IOTA WITH STROKE', +7549: 'LATIN SMALL LETTER P WITH STROKE', +7550: 'LATIN SMALL CAPITAL LETTER U WITH STROKE', +7551: 'LATIN SMALL LETTER UPSILON WITH STROKE', +7552: 'LATIN SMALL LETTER B WITH PALATAL HOOK', +7553: 'LATIN SMALL LETTER D WITH PALATAL HOOK', +7554: 'LATIN SMALL LETTER F WITH PALATAL HOOK', +7555: 'LATIN SMALL LETTER G WITH PALATAL HOOK', +7556: 'LATIN SMALL LETTER K WITH PALATAL HOOK', +7557: 'LATIN SMALL LETTER L WITH PALATAL HOOK', +7558: 'LATIN SMALL LETTER M WITH PALATAL HOOK', +7559: 'LATIN SMALL LETTER N WITH PALATAL HOOK', +7560: 'LATIN SMALL LETTER P WITH PALATAL HOOK', +7561: 'LATIN SMALL LETTER R WITH PALATAL HOOK', +7562: 'LATIN SMALL LETTER S WITH PALATAL HOOK', +7563: 'LATIN SMALL LETTER ESH WITH PALATAL HOOK', +7564: 'LATIN SMALL LETTER V WITH PALATAL HOOK', +7565: 'LATIN SMALL LETTER X WITH PALATAL HOOK', +7566: 'LATIN SMALL LETTER Z WITH PALATAL HOOK', +7567: 'LATIN SMALL LETTER A WITH RETROFLEX HOOK', +7568: 'LATIN SMALL LETTER ALPHA WITH RETROFLEX HOOK', +7569: 'LATIN SMALL LETTER D WITH HOOK AND TAIL', +7570: 'LATIN SMALL LETTER E WITH RETROFLEX HOOK', +7571: 'LATIN SMALL LETTER OPEN E WITH RETROFLEX HOOK', +7572: 'LATIN SMALL LETTER REVERSED OPEN E WITH RETROFLEX HOOK', +7573: 'LATIN SMALL LETTER SCHWA WITH RETROFLEX HOOK', +7574: 'LATIN SMALL LETTER I WITH RETROFLEX HOOK', +7575: 'LATIN SMALL LETTER OPEN O WITH RETROFLEX HOOK', +7576: 'LATIN SMALL LETTER ESH WITH RETROFLEX HOOK', +7577: 'LATIN SMALL LETTER U WITH RETROFLEX HOOK', +7578: 'LATIN SMALL LETTER EZH WITH RETROFLEX HOOK', +7579: 'MODIFIER LETTER SMALL TURNED ALPHA', +7580: 'MODIFIER LETTER SMALL C', +7581: 'MODIFIER LETTER SMALL C WITH CURL', +7582: 'MODIFIER LETTER SMALL ETH', +7583: 'MODIFIER LETTER SMALL REVERSED OPEN E', +7584: 'MODIFIER LETTER SMALL F', +7585: 'MODIFIER LETTER SMALL DOTLESS J WITH STROKE', +7586: 'MODIFIER LETTER SMALL SCRIPT G', +7587: 'MODIFIER LETTER SMALL TURNED H', +7588: 'MODIFIER LETTER SMALL I WITH STROKE', +7589: 'MODIFIER LETTER SMALL IOTA', +7590: 'MODIFIER LETTER SMALL CAPITAL I', +7591: 'MODIFIER LETTER SMALL CAPITAL I WITH STROKE', +7592: 'MODIFIER LETTER SMALL J WITH CROSSED-TAIL', +7593: 'MODIFIER LETTER SMALL L WITH RETROFLEX HOOK', +7594: 'MODIFIER LETTER SMALL L WITH PALATAL HOOK', +7595: 'MODIFIER LETTER SMALL CAPITAL L', +7596: 'MODIFIER LETTER SMALL M WITH HOOK', +7597: 'MODIFIER LETTER SMALL TURNED M WITH LONG LEG', +7598: 'MODIFIER LETTER SMALL N WITH LEFT HOOK', +7599: 'MODIFIER LETTER SMALL N WITH RETROFLEX HOOK', +7600: 'MODIFIER LETTER SMALL CAPITAL N', +7601: 'MODIFIER LETTER SMALL BARRED O', +7602: 'MODIFIER LETTER SMALL PHI', +7603: 'MODIFIER LETTER SMALL S WITH HOOK', +7604: 'MODIFIER LETTER SMALL ESH', +7605: 'MODIFIER LETTER SMALL T WITH PALATAL HOOK', +7606: 'MODIFIER LETTER SMALL U BAR', +7607: 'MODIFIER LETTER SMALL UPSILON', +7608: 'MODIFIER LETTER SMALL CAPITAL U', +7609: 'MODIFIER LETTER SMALL V WITH HOOK', +7610: 'MODIFIER LETTER SMALL TURNED V', +7611: 'MODIFIER LETTER SMALL Z', +7612: 'MODIFIER LETTER SMALL Z WITH RETROFLEX HOOK', +7613: 'MODIFIER LETTER SMALL Z WITH CURL', +7614: 'MODIFIER LETTER SMALL EZH', +7615: 'MODIFIER LETTER SMALL THETA', +7616: 'COMBINING DOTTED GRAVE ACCENT', +7617: 'COMBINING DOTTED ACUTE ACCENT', +7618: 'COMBINING SNAKE BELOW', +7619: 'COMBINING SUSPENSION MARK', 7680: 'LATIN CAPITAL LETTER A WITH RING BELOW', 7681: 'LATIN SMALL LETTER A WITH RING BELOW', 7682: 'LATIN CAPITAL LETTER B WITH DOT ABOVE', @@ -5248,7 +5893,18 @@ 8272: 'CLOSE UP', 8273: 'TWO ASTERISKS ALIGNED VERTICALLY', 8274: 'COMMERCIAL MINUS SIGN', +8275: 'SWUNG DASH', +8276: 'INVERTED UNDERTIE', +8277: 'FLOWER PUNCTUATION MARK', +8278: 'THREE DOT PUNCTUATION', 8279: 'QUADRUPLE PRIME', +8280: 'FOUR DOT PUNCTUATION', +8281: 'FIVE DOT PUNCTUATION', +8282: 'TWO DOT PUNCTUATION', +8283: 'FOUR DOT MARK', +8284: 'DOTTED CROSS', +8285: 'TRICOLON', +8286: 'VERTICAL FOUR DOTS', 8287: 'MEDIUM MATHEMATICAL SPACE', 8288: 'WORD JOINER', 8289: 'FUNCTION APPLICATION', @@ -5289,6 +5945,11 @@ 8332: 'SUBSCRIPT EQUALS SIGN', 8333: 'SUBSCRIPT LEFT PARENTHESIS', 8334: 'SUBSCRIPT RIGHT PARENTHESIS', +8336: 'LATIN SUBSCRIPT SMALL LETTER A', +8337: 'LATIN SUBSCRIPT SMALL LETTER E', +8338: 'LATIN SUBSCRIPT SMALL LETTER O', +8339: 'LATIN SUBSCRIPT SMALL LETTER X', +8340: 'LATIN SUBSCRIPT SMALL LETTER SCHWA', 8352: 'EURO-CURRENCY SIGN', 8353: 'COLON SIGN', 8354: 'CRUZEIRO SIGN', @@ -5307,6 +5968,10 @@ 8367: 'DRACHMA SIGN', 8368: 'GERMAN PENNY SIGN', 8369: 'PESO SIGN', +8370: 'GUARANI SIGN', +8371: 'AUSTRAL SIGN', +8372: 'HRYVNIA SIGN', +8373: 'CEDI SIGN', 8400: 'COMBINING LEFT HARPOON ABOVE', 8401: 'COMBINING RIGHT HARPOON ABOVE', 8402: 'COMBINING LONG VERTICAL LINE OVERLAY', @@ -5334,6 +5999,7 @@ 8424: 'COMBINING TRIPLE UNDERDOT', 8425: 'COMBINING WIDE BRIDGE ABOVE', 8426: 'COMBINING LEFTWARDS ARROW OVERLAY', +8427: 'COMBINING LONG DOUBLE SOLIDUS OVERLAY', 8448: 'ACCOUNT OF', 8449: 'ADDRESSED TO THE SUBJECT', 8450: 'DOUBLE-STRUCK CAPITAL C', @@ -5393,6 +6059,8 @@ 8504: 'DALET SYMBOL', 8505: 'INFORMATION SOURCE', 8506: 'ROTATED CAPITAL Q', +8507: 'FACSIMILE SIGN', +8508: 'DOUBLE-STRUCK SMALL PI', 8509: 'DOUBLE-STRUCK SMALL GAMMA', 8510: 'DOUBLE-STRUCK CAPITAL GAMMA', 8511: 'DOUBLE-STRUCK CAPITAL PI', @@ -5408,6 +6076,7 @@ 8521: 'DOUBLE-STRUCK ITALIC SMALL J', 8522: 'PROPERTY LINE', 8523: 'TURNED AMPERSAND', +8524: 'PER SIGN', 8531: 'VULGAR FRACTION ONE THIRD', 8532: 'VULGAR FRACTION TWO THIRDS', 8533: 'VULGAR FRACTION ONE FIFTH', @@ -6032,6 +6701,19 @@ 9164: 'DENTISTRY SYMBOL LIGHT VERTICAL AND BOTTOM LEFT', 9165: 'SQUARE FOOT', 9166: 'RETURN SYMBOL', +9167: 'EJECT SYMBOL', +9168: 'VERTICAL LINE EXTENSION', +9169: 'METRICAL BREVE', +9170: 'METRICAL LONG OVER SHORT', +9171: 'METRICAL SHORT OVER LONG', +9172: 'METRICAL LONG OVER TWO SHORTS', +9173: 'METRICAL TWO SHORTS OVER LONG', +9174: 'METRICAL TWO SHORTS JOINED', +9175: 'METRICAL TRISEME', +9176: 'METRICAL TETRASEME', +9177: 'METRICAL PENTASEME', +9178: 'EARTH GROUND', +9179: 'FUSE', 9216: 'SYMBOL FOR NULL', 9217: 'SYMBOL FOR START OF HEADING', 9218: 'SYMBOL FOR START OF TEXT', @@ -6241,6 +6923,7 @@ 9468: 'DOUBLE CIRCLED DIGIT EIGHT', 9469: 'DOUBLE CIRCLED DIGIT NINE', 9470: 'DOUBLE CIRCLED NUMBER TEN', +9471: 'NEGATIVE CIRCLED DIGIT ZERO', 9472: 'BOX DRAWINGS LIGHT HORIZONTAL', 9473: 'BOX DRAWINGS HEAVY HORIZONTAL', 9474: 'BOX DRAWINGS LIGHT VERTICAL', @@ -6517,8 +7200,11 @@ 9745: 'BALLOT BOX WITH CHECK', 9746: 'BALLOT BOX WITH X', 9747: 'SALTIRE', +9748: 'UMBRELLA WITH RAIN DROPS', +9749: 'HOT BEVERAGE', 9750: 'WHITE SHOGI PIECE', 9751: 'BLACK SHOGI PIECE', +9752: 'SHAMROCK', 9753: 'REVERSED ROTATED FLORAL HEART BULLET', 9754: 'BLACK LEFT POINTING INDEX', 9755: 'BLACK RIGHT POINTING INDEX', @@ -6620,6 +7306,8 @@ 9851: 'BLACK UNIVERSAL RECYCLING SYMBOL', 9852: 'RECYCLED PAPER SYMBOL', 9853: 'PARTIALLY-RECYCLED PAPER SYMBOL', +9854: 'PERMANENT PAPER SIGN', +9855: 'WHEELCHAIR SYMBOL', 9856: 'DIE FACE-1', 9857: 'DIE FACE-2', 9858: 'DIE FACE-3', @@ -6630,6 +7318,43 @@ 9863: 'WHITE CIRCLE WITH TWO DOTS', 9864: 'BLACK CIRCLE WITH WHITE DOT RIGHT', 9865: 'BLACK CIRCLE WITH TWO WHITE DOTS', +9866: 'MONOGRAM FOR YANG', +9867: 'MONOGRAM FOR YIN', +9868: 'DIGRAM FOR GREATER YANG', +9869: 'DIGRAM FOR LESSER YIN', +9870: 'DIGRAM FOR LESSER YANG', +9871: 'DIGRAM FOR GREATER YIN', +9872: 'WHITE FLAG', +9873: 'BLACK FLAG', +9874: 'HAMMER AND PICK', +9875: 'ANCHOR', +9876: 'CROSSED SWORDS', +9877: 'STAFF OF AESCULAPIUS', +9878: 'SCALES', +9879: 'ALEMBIC', +9880: 'FLOWER', +9881: 'GEAR', +9882: 'STAFF OF HERMES', +9883: 'ATOM SYMBOL', +9884: 'FLEUR-DE-LIS', +9888: 'WARNING SIGN', +9889: 'HIGH VOLTAGE SIGN', +9890: 'DOUBLED FEMALE SIGN', +9891: 'DOUBLED MALE SIGN', +9892: 'INTERLOCKED FEMALE AND MALE SIGN', +9893: 'MALE AND FEMALE SIGN', +9894: 'MALE WITH STROKE SIGN', +9895: 'MALE WITH STROKE AND MALE AND FEMALE SIGN', +9896: 'VERTICAL MALE WITH STROKE SIGN', +9897: 'HORIZONTAL MALE WITH STROKE SIGN', +9898: 'MEDIUM WHITE CIRCLE', +9899: 'MEDIUM BLACK CIRCLE', +9900: 'MEDIUM SMALL WHITE CIRCLE', +9901: 'MARRIAGE SYMBOL', +9902: 'DIVORCE SYMBOL', +9903: 'UNMARRIED PARTNERSHIP SYMBOL', +9904: 'COFFIN', +9905: 'FUNERAL URN', 9985: 'UPPER BLADE SCISSORS', 9986: 'BLACK SCISSORS', 9987: 'LOWER BLADE SCISSORS', @@ -6804,6 +7529,13 @@ 10172: 'WEDGE-TAILED RIGHTWARDS ARROW', 10173: 'HEAVY WEDGE-TAILED RIGHTWARDS ARROW', 10174: 'OPEN-OUTLINED RIGHTWARDS ARROW', +10176: 'THREE DIMENSIONAL ANGLE', +10177: 'WHITE TRIANGLE CONTAINING SMALL WHITE TRIANGLE', +10178: 'PERPENDICULAR', +10179: 'OPEN SUBSET', +10180: 'OPEN SUPERSET', +10181: 'LEFT S-SHAPED BAG DELIMITER', +10182: 'RIGHT S-SHAPED BAG DELIMITER', 10192: 'WHITE DIAMOND WITH CENTRED DOT', 10193: 'AND WITH DOT', 10194: 'ELEMENT OF OPENING UPWARDS', @@ -7616,6 +8348,432 @@ 11005: 'DOUBLE SOLIDUS OPERATOR', 11006: 'WHITE VERTICAL BAR', 11007: 'N-ARY WHITE VERTICAL BAR', +11008: 'NORTH EAST WHITE ARROW', +11009: 'NORTH WEST WHITE ARROW', +11010: 'SOUTH EAST WHITE ARROW', +11011: 'SOUTH WEST WHITE ARROW', +11012: 'LEFT RIGHT WHITE ARROW', +11013: 'LEFTWARDS BLACK ARROW', +11014: 'UPWARDS BLACK ARROW', +11015: 'DOWNWARDS BLACK ARROW', +11016: 'NORTH EAST BLACK ARROW', +11017: 'NORTH WEST BLACK ARROW', +11018: 'SOUTH EAST BLACK ARROW', +11019: 'SOUTH WEST BLACK ARROW', +11020: 'LEFT RIGHT BLACK ARROW', +11021: 'UP DOWN BLACK ARROW', +11022: 'RIGHTWARDS ARROW WITH TIP DOWNWARDS', +11023: 'RIGHTWARDS ARROW WITH TIP UPWARDS', +11024: 'LEFTWARDS ARROW WITH TIP DOWNWARDS', +11025: 'LEFTWARDS ARROW WITH TIP UPWARDS', +11026: 'SQUARE WITH TOP HALF BLACK', +11027: 'SQUARE WITH BOTTOM HALF BLACK', +11264: 'GLAGOLITIC CAPITAL LETTER AZU', +11265: 'GLAGOLITIC CAPITAL LETTER BUKY', +11266: 'GLAGOLITIC CAPITAL LETTER VEDE', +11267: 'GLAGOLITIC CAPITAL LETTER GLAGOLI', +11268: 'GLAGOLITIC CAPITAL LETTER DOBRO', +11269: 'GLAGOLITIC CAPITAL LETTER YESTU', +11270: 'GLAGOLITIC CAPITAL LETTER ZHIVETE', +11271: 'GLAGOLITIC CAPITAL LETTER DZELO', +11272: 'GLAGOLITIC CAPITAL LETTER ZEMLJA', +11273: 'GLAGOLITIC CAPITAL LETTER IZHE', +11274: 'GLAGOLITIC CAPITAL LETTER INITIAL IZHE', +11275: 'GLAGOLITIC CAPITAL LETTER I', +11276: 'GLAGOLITIC CAPITAL LETTER DJERVI', +11277: 'GLAGOLITIC CAPITAL LETTER KAKO', +11278: 'GLAGOLITIC CAPITAL LETTER LJUDIJE', +11279: 'GLAGOLITIC CAPITAL LETTER MYSLITE', +11280: 'GLAGOLITIC CAPITAL LETTER NASHI', +11281: 'GLAGOLITIC CAPITAL LETTER ONU', +11282: 'GLAGOLITIC CAPITAL LETTER POKOJI', +11283: 'GLAGOLITIC CAPITAL LETTER RITSI', +11284: 'GLAGOLITIC CAPITAL LETTER SLOVO', +11285: 'GLAGOLITIC CAPITAL LETTER TVRIDO', +11286: 'GLAGOLITIC CAPITAL LETTER UKU', +11287: 'GLAGOLITIC CAPITAL LETTER FRITU', +11288: 'GLAGOLITIC CAPITAL LETTER HERU', +11289: 'GLAGOLITIC CAPITAL LETTER OTU', +11290: 'GLAGOLITIC CAPITAL LETTER PE', +11291: 'GLAGOLITIC CAPITAL LETTER SHTA', +11292: 'GLAGOLITIC CAPITAL LETTER TSI', +11293: 'GLAGOLITIC CAPITAL LETTER CHRIVI', +11294: 'GLAGOLITIC CAPITAL LETTER SHA', +11295: 'GLAGOLITIC CAPITAL LETTER YERU', +11296: 'GLAGOLITIC CAPITAL LETTER YERI', +11297: 'GLAGOLITIC CAPITAL LETTER YATI', +11298: 'GLAGOLITIC CAPITAL LETTER SPIDERY HA', +11299: 'GLAGOLITIC CAPITAL LETTER YU', +11300: 'GLAGOLITIC CAPITAL LETTER SMALL YUS', +11301: 'GLAGOLITIC CAPITAL LETTER SMALL YUS WITH TAIL', +11302: 'GLAGOLITIC CAPITAL LETTER YO', +11303: 'GLAGOLITIC CAPITAL LETTER IOTATED SMALL YUS', +11304: 'GLAGOLITIC CAPITAL LETTER BIG YUS', +11305: 'GLAGOLITIC CAPITAL LETTER IOTATED BIG YUS', +11306: 'GLAGOLITIC CAPITAL LETTER FITA', +11307: 'GLAGOLITIC CAPITAL LETTER IZHITSA', +11308: 'GLAGOLITIC CAPITAL LETTER SHTAPIC', +11309: 'GLAGOLITIC CAPITAL LETTER TROKUTASTI A', +11310: 'GLAGOLITIC CAPITAL LETTER LATINATE MYSLITE', +11312: 'GLAGOLITIC SMALL LETTER AZU', +11313: 'GLAGOLITIC SMALL LETTER BUKY', +11314: 'GLAGOLITIC SMALL LETTER VEDE', +11315: 'GLAGOLITIC SMALL LETTER GLAGOLI', +11316: 'GLAGOLITIC SMALL LETTER DOBRO', +11317: 'GLAGOLITIC SMALL LETTER YESTU', +11318: 'GLAGOLITIC SMALL LETTER ZHIVETE', +11319: 'GLAGOLITIC SMALL LETTER DZELO', +11320: 'GLAGOLITIC SMALL LETTER ZEMLJA', +11321: 'GLAGOLITIC SMALL LETTER IZHE', +11322: 'GLAGOLITIC SMALL LETTER INITIAL IZHE', +11323: 'GLAGOLITIC SMALL LETTER I', +11324: 'GLAGOLITIC SMALL LETTER DJERVI', +11325: 'GLAGOLITIC SMALL LETTER KAKO', +11326: 'GLAGOLITIC SMALL LETTER LJUDIJE', +11327: 'GLAGOLITIC SMALL LETTER MYSLITE', +11328: 'GLAGOLITIC SMALL LETTER NASHI', +11329: 'GLAGOLITIC SMALL LETTER ONU', +11330: 'GLAGOLITIC SMALL LETTER POKOJI', +11331: 'GLAGOLITIC SMALL LETTER RITSI', +11332: 'GLAGOLITIC SMALL LETTER SLOVO', +11333: 'GLAGOLITIC SMALL LETTER TVRIDO', +11334: 'GLAGOLITIC SMALL LETTER UKU', +11335: 'GLAGOLITIC SMALL LETTER FRITU', +11336: 'GLAGOLITIC SMALL LETTER HERU', +11337: 'GLAGOLITIC SMALL LETTER OTU', +11338: 'GLAGOLITIC SMALL LETTER PE', +11339: 'GLAGOLITIC SMALL LETTER SHTA', +11340: 'GLAGOLITIC SMALL LETTER TSI', +11341: 'GLAGOLITIC SMALL LETTER CHRIVI', +11342: 'GLAGOLITIC SMALL LETTER SHA', +11343: 'GLAGOLITIC SMALL LETTER YERU', +11344: 'GLAGOLITIC SMALL LETTER YERI', +11345: 'GLAGOLITIC SMALL LETTER YATI', +11346: 'GLAGOLITIC SMALL LETTER SPIDERY HA', +11347: 'GLAGOLITIC SMALL LETTER YU', +11348: 'GLAGOLITIC SMALL LETTER SMALL YUS', +11349: 'GLAGOLITIC SMALL LETTER SMALL YUS WITH TAIL', +11350: 'GLAGOLITIC SMALL LETTER YO', +11351: 'GLAGOLITIC SMALL LETTER IOTATED SMALL YUS', +11352: 'GLAGOLITIC SMALL LETTER BIG YUS', +11353: 'GLAGOLITIC SMALL LETTER IOTATED BIG YUS', +11354: 'GLAGOLITIC SMALL LETTER FITA', +11355: 'GLAGOLITIC SMALL LETTER IZHITSA', +11356: 'GLAGOLITIC SMALL LETTER SHTAPIC', +11357: 'GLAGOLITIC SMALL LETTER TROKUTASTI A', +11358: 'GLAGOLITIC SMALL LETTER LATINATE MYSLITE', +11392: 'COPTIC CAPITAL LETTER ALFA', +11393: 'COPTIC SMALL LETTER ALFA', +11394: 'COPTIC CAPITAL LETTER VIDA', +11395: 'COPTIC SMALL LETTER VIDA', +11396: 'COPTIC CAPITAL LETTER GAMMA', +11397: 'COPTIC SMALL LETTER GAMMA', +11398: 'COPTIC CAPITAL LETTER DALDA', +11399: 'COPTIC SMALL LETTER DALDA', +11400: 'COPTIC CAPITAL LETTER EIE', +11401: 'COPTIC SMALL LETTER EIE', +11402: 'COPTIC CAPITAL LETTER SOU', +11403: 'COPTIC SMALL LETTER SOU', +11404: 'COPTIC CAPITAL LETTER ZATA', +11405: 'COPTIC SMALL LETTER ZATA', +11406: 'COPTIC CAPITAL LETTER HATE', +11407: 'COPTIC SMALL LETTER HATE', +11408: 'COPTIC CAPITAL LETTER THETHE', +11409: 'COPTIC SMALL LETTER THETHE', +11410: 'COPTIC CAPITAL LETTER IAUDA', +11411: 'COPTIC SMALL LETTER IAUDA', +11412: 'COPTIC CAPITAL LETTER KAPA', +11413: 'COPTIC SMALL LETTER KAPA', +11414: 'COPTIC CAPITAL LETTER LAULA', +11415: 'COPTIC SMALL LETTER LAULA', +11416: 'COPTIC CAPITAL LETTER MI', +11417: 'COPTIC SMALL LETTER MI', +11418: 'COPTIC CAPITAL LETTER NI', +11419: 'COPTIC SMALL LETTER NI', +11420: 'COPTIC CAPITAL LETTER KSI', +11421: 'COPTIC SMALL LETTER KSI', +11422: 'COPTIC CAPITAL LETTER O', +11423: 'COPTIC SMALL LETTER O', +11424: 'COPTIC CAPITAL LETTER PI', +11425: 'COPTIC SMALL LETTER PI', +11426: 'COPTIC CAPITAL LETTER RO', +11427: 'COPTIC SMALL LETTER RO', +11428: 'COPTIC CAPITAL LETTER SIMA', +11429: 'COPTIC SMALL LETTER SIMA', +11430: 'COPTIC CAPITAL LETTER TAU', +11431: 'COPTIC SMALL LETTER TAU', +11432: 'COPTIC CAPITAL LETTER UA', +11433: 'COPTIC SMALL LETTER UA', +11434: 'COPTIC CAPITAL LETTER FI', +11435: 'COPTIC SMALL LETTER FI', +11436: 'COPTIC CAPITAL LETTER KHI', +11437: 'COPTIC SMALL LETTER KHI', +11438: 'COPTIC CAPITAL LETTER PSI', +11439: 'COPTIC SMALL LETTER PSI', +11440: 'COPTIC CAPITAL LETTER OOU', +11441: 'COPTIC SMALL LETTER OOU', +11442: 'COPTIC CAPITAL LETTER DIALECT-P ALEF', +11443: 'COPTIC SMALL LETTER DIALECT-P ALEF', +11444: 'COPTIC CAPITAL LETTER OLD COPTIC AIN', +11445: 'COPTIC SMALL LETTER OLD COPTIC AIN', +11446: 'COPTIC CAPITAL LETTER CRYPTOGRAMMIC EIE', +11447: 'COPTIC SMALL LETTER CRYPTOGRAMMIC EIE', +11448: 'COPTIC CAPITAL LETTER DIALECT-P KAPA', +11449: 'COPTIC SMALL LETTER DIALECT-P KAPA', +11450: 'COPTIC CAPITAL LETTER DIALECT-P NI', +11451: 'COPTIC SMALL LETTER DIALECT-P NI', +11452: 'COPTIC CAPITAL LETTER CRYPTOGRAMMIC NI', +11453: 'COPTIC SMALL LETTER CRYPTOGRAMMIC NI', +11454: 'COPTIC CAPITAL LETTER OLD COPTIC OOU', +11455: 'COPTIC SMALL LETTER OLD COPTIC OOU', +11456: 'COPTIC CAPITAL LETTER SAMPI', +11457: 'COPTIC SMALL LETTER SAMPI', +11458: 'COPTIC CAPITAL LETTER CROSSED SHEI', +11459: 'COPTIC SMALL LETTER CROSSED SHEI', +11460: 'COPTIC CAPITAL LETTER OLD COPTIC SHEI', +11461: 'COPTIC SMALL LETTER OLD COPTIC SHEI', +11462: 'COPTIC CAPITAL LETTER OLD COPTIC ESH', +11463: 'COPTIC SMALL LETTER OLD COPTIC ESH', +11464: 'COPTIC CAPITAL LETTER AKHMIMIC KHEI', +11465: 'COPTIC SMALL LETTER AKHMIMIC KHEI', +11466: 'COPTIC CAPITAL LETTER DIALECT-P HORI', +11467: 'COPTIC SMALL LETTER DIALECT-P HORI', +11468: 'COPTIC CAPITAL LETTER OLD COPTIC HORI', +11469: 'COPTIC SMALL LETTER OLD COPTIC HORI', +11470: 'COPTIC CAPITAL LETTER OLD COPTIC HA', +11471: 'COPTIC SMALL LETTER OLD COPTIC HA', +11472: 'COPTIC CAPITAL LETTER L-SHAPED HA', +11473: 'COPTIC SMALL LETTER L-SHAPED HA', +11474: 'COPTIC CAPITAL LETTER OLD COPTIC HEI', +11475: 'COPTIC SMALL LETTER OLD COPTIC HEI', +11476: 'COPTIC CAPITAL LETTER OLD COPTIC HAT', +11477: 'COPTIC SMALL LETTER OLD COPTIC HAT', +11478: 'COPTIC CAPITAL LETTER OLD COPTIC GANGIA', +11479: 'COPTIC SMALL LETTER OLD COPTIC GANGIA', +11480: 'COPTIC CAPITAL LETTER OLD COPTIC DJA', +11481: 'COPTIC SMALL LETTER OLD COPTIC DJA', +11482: 'COPTIC CAPITAL LETTER OLD COPTIC SHIMA', +11483: 'COPTIC SMALL LETTER OLD COPTIC SHIMA', +11484: 'COPTIC CAPITAL LETTER OLD NUBIAN SHIMA', +11485: 'COPTIC SMALL LETTER OLD NUBIAN SHIMA', +11486: 'COPTIC CAPITAL LETTER OLD NUBIAN NGI', +11487: 'COPTIC SMALL LETTER OLD NUBIAN NGI', +11488: 'COPTIC CAPITAL LETTER OLD NUBIAN NYI', +11489: 'COPTIC SMALL LETTER OLD NUBIAN NYI', +11490: 'COPTIC CAPITAL LETTER OLD NUBIAN WAU', +11491: 'COPTIC SMALL LETTER OLD NUBIAN WAU', +11492: 'COPTIC SYMBOL KAI', +11493: 'COPTIC SYMBOL MI RO', +11494: 'COPTIC SYMBOL PI RO', +11495: 'COPTIC SYMBOL STAUROS', +11496: 'COPTIC SYMBOL TAU RO', +11497: 'COPTIC SYMBOL KHI RO', +11498: 'COPTIC SYMBOL SHIMA SIMA', +11513: 'COPTIC OLD NUBIAN FULL STOP', +11514: 'COPTIC OLD NUBIAN DIRECT QUESTION MARK', +11515: 'COPTIC OLD NUBIAN INDIRECT QUESTION MARK', +11516: 'COPTIC OLD NUBIAN VERSE DIVIDER', +11517: 'COPTIC FRACTION ONE HALF', +11518: 'COPTIC FULL STOP', +11519: 'COPTIC MORPHOLOGICAL DIVIDER', +11520: 'GEORGIAN SMALL LETTER AN', +11521: 'GEORGIAN SMALL LETTER BAN', +11522: 'GEORGIAN SMALL LETTER GAN', +11523: 'GEORGIAN SMALL LETTER DON', +11524: 'GEORGIAN SMALL LETTER EN', +11525: 'GEORGIAN SMALL LETTER VIN', +11526: 'GEORGIAN SMALL LETTER ZEN', +11527: 'GEORGIAN SMALL LETTER TAN', +11528: 'GEORGIAN SMALL LETTER IN', +11529: 'GEORGIAN SMALL LETTER KAN', +11530: 'GEORGIAN SMALL LETTER LAS', +11531: 'GEORGIAN SMALL LETTER MAN', +11532: 'GEORGIAN SMALL LETTER NAR', +11533: 'GEORGIAN SMALL LETTER ON', +11534: 'GEORGIAN SMALL LETTER PAR', +11535: 'GEORGIAN SMALL LETTER ZHAR', +11536: 'GEORGIAN SMALL LETTER RAE', +11537: 'GEORGIAN SMALL LETTER SAN', +11538: 'GEORGIAN SMALL LETTER TAR', +11539: 'GEORGIAN SMALL LETTER UN', +11540: 'GEORGIAN SMALL LETTER PHAR', +11541: 'GEORGIAN SMALL LETTER KHAR', +11542: 'GEORGIAN SMALL LETTER GHAN', +11543: 'GEORGIAN SMALL LETTER QAR', +11544: 'GEORGIAN SMALL LETTER SHIN', +11545: 'GEORGIAN SMALL LETTER CHIN', +11546: 'GEORGIAN SMALL LETTER CAN', +11547: 'GEORGIAN SMALL LETTER JIL', +11548: 'GEORGIAN SMALL LETTER CIL', +11549: 'GEORGIAN SMALL LETTER CHAR', +11550: 'GEORGIAN SMALL LETTER XAN', +11551: 'GEORGIAN SMALL LETTER JHAN', +11552: 'GEORGIAN SMALL LETTER HAE', +11553: 'GEORGIAN SMALL LETTER HE', +11554: 'GEORGIAN SMALL LETTER HIE', +11555: 'GEORGIAN SMALL LETTER WE', +11556: 'GEORGIAN SMALL LETTER HAR', +11557: 'GEORGIAN SMALL LETTER HOE', +11568: 'TIFINAGH LETTER YA', +11569: 'TIFINAGH LETTER YAB', +11570: 'TIFINAGH LETTER YABH', +11571: 'TIFINAGH LETTER YAG', +11572: 'TIFINAGH LETTER YAGHH', +11573: 'TIFINAGH LETTER BERBER ACADEMY YAJ', +11574: 'TIFINAGH LETTER YAJ', +11575: 'TIFINAGH LETTER YAD', +11576: 'TIFINAGH LETTER YADH', +11577: 'TIFINAGH LETTER YADD', +11578: 'TIFINAGH LETTER YADDH', +11579: 'TIFINAGH LETTER YEY', +11580: 'TIFINAGH LETTER YAF', +11581: 'TIFINAGH LETTER YAK', +11582: 'TIFINAGH LETTER TUAREG YAK', +11583: 'TIFINAGH LETTER YAKHH', +11584: 'TIFINAGH LETTER YAH', +11585: 'TIFINAGH LETTER BERBER ACADEMY YAH', +11586: 'TIFINAGH LETTER TUAREG YAH', +11587: 'TIFINAGH LETTER YAHH', +11588: 'TIFINAGH LETTER YAA', +11589: 'TIFINAGH LETTER YAKH', +11590: 'TIFINAGH LETTER TUAREG YAKH', +11591: 'TIFINAGH LETTER YAQ', +11592: 'TIFINAGH LETTER TUAREG YAQ', +11593: 'TIFINAGH LETTER YI', +11594: 'TIFINAGH LETTER YAZH', +11595: 'TIFINAGH LETTER AHAGGAR YAZH', +11596: 'TIFINAGH LETTER TUAREG YAZH', +11597: 'TIFINAGH LETTER YAL', +11598: 'TIFINAGH LETTER YAM', +11599: 'TIFINAGH LETTER YAN', +11600: 'TIFINAGH LETTER TUAREG YAGN', +11601: 'TIFINAGH LETTER TUAREG YANG', +11602: 'TIFINAGH LETTER YAP', +11603: 'TIFINAGH LETTER YU', +11604: 'TIFINAGH LETTER YAR', +11605: 'TIFINAGH LETTER YARR', +11606: 'TIFINAGH LETTER YAGH', +11607: 'TIFINAGH LETTER TUAREG YAGH', +11608: 'TIFINAGH LETTER AYER YAGH', +11609: 'TIFINAGH LETTER YAS', +11610: 'TIFINAGH LETTER YASS', +11611: 'TIFINAGH LETTER YASH', +11612: 'TIFINAGH LETTER YAT', +11613: 'TIFINAGH LETTER YATH', +11614: 'TIFINAGH LETTER YACH', +11615: 'TIFINAGH LETTER YATT', +11616: 'TIFINAGH LETTER YAV', +11617: 'TIFINAGH LETTER YAW', +11618: 'TIFINAGH LETTER YAY', +11619: 'TIFINAGH LETTER YAZ', +11620: 'TIFINAGH LETTER TAWELLEMET YAZ', +11621: 'TIFINAGH LETTER YAZZ', +11631: 'TIFINAGH MODIFIER LETTER LABIALIZATION MARK', +11648: 'ETHIOPIC SYLLABLE LOA', +11649: 'ETHIOPIC SYLLABLE MOA', +11650: 'ETHIOPIC SYLLABLE ROA', +11651: 'ETHIOPIC SYLLABLE SOA', +11652: 'ETHIOPIC SYLLABLE SHOA', +11653: 'ETHIOPIC SYLLABLE BOA', +11654: 'ETHIOPIC SYLLABLE TOA', +11655: 'ETHIOPIC SYLLABLE COA', +11656: 'ETHIOPIC SYLLABLE NOA', +11657: 'ETHIOPIC SYLLABLE NYOA', +11658: 'ETHIOPIC SYLLABLE GLOTTAL OA', +11659: 'ETHIOPIC SYLLABLE ZOA', +11660: 'ETHIOPIC SYLLABLE DOA', +11661: 'ETHIOPIC SYLLABLE DDOA', +11662: 'ETHIOPIC SYLLABLE JOA', +11663: 'ETHIOPIC SYLLABLE THOA', +11664: 'ETHIOPIC SYLLABLE CHOA', +11665: 'ETHIOPIC SYLLABLE PHOA', +11666: 'ETHIOPIC SYLLABLE POA', +11667: 'ETHIOPIC SYLLABLE GGWA', +11668: 'ETHIOPIC SYLLABLE GGWI', +11669: 'ETHIOPIC SYLLABLE GGWEE', +11670: 'ETHIOPIC SYLLABLE GGWE', +11680: 'ETHIOPIC SYLLABLE SSA', +11681: 'ETHIOPIC SYLLABLE SSU', +11682: 'ETHIOPIC SYLLABLE SSI', +11683: 'ETHIOPIC SYLLABLE SSAA', +11684: 'ETHIOPIC SYLLABLE SSEE', +11685: 'ETHIOPIC SYLLABLE SSE', +11686: 'ETHIOPIC SYLLABLE SSO', +11688: 'ETHIOPIC SYLLABLE CCA', +11689: 'ETHIOPIC SYLLABLE CCU', +11690: 'ETHIOPIC SYLLABLE CCI', +11691: 'ETHIOPIC SYLLABLE CCAA', +11692: 'ETHIOPIC SYLLABLE CCEE', +11693: 'ETHIOPIC SYLLABLE CCE', +11694: 'ETHIOPIC SYLLABLE CCO', +11696: 'ETHIOPIC SYLLABLE ZZA', +11697: 'ETHIOPIC SYLLABLE ZZU', +11698: 'ETHIOPIC SYLLABLE ZZI', +11699: 'ETHIOPIC SYLLABLE ZZAA', +11700: 'ETHIOPIC SYLLABLE ZZEE', +11701: 'ETHIOPIC SYLLABLE ZZE', +11702: 'ETHIOPIC SYLLABLE ZZO', +11704: 'ETHIOPIC SYLLABLE CCHA', +11705: 'ETHIOPIC SYLLABLE CCHU', +11706: 'ETHIOPIC SYLLABLE CCHI', +11707: 'ETHIOPIC SYLLABLE CCHAA', +11708: 'ETHIOPIC SYLLABLE CCHEE', +11709: 'ETHIOPIC SYLLABLE CCHE', +11710: 'ETHIOPIC SYLLABLE CCHO', +11712: 'ETHIOPIC SYLLABLE QYA', +11713: 'ETHIOPIC SYLLABLE QYU', +11714: 'ETHIOPIC SYLLABLE QYI', +11715: 'ETHIOPIC SYLLABLE QYAA', +11716: 'ETHIOPIC SYLLABLE QYEE', +11717: 'ETHIOPIC SYLLABLE QYE', +11718: 'ETHIOPIC SYLLABLE QYO', +11720: 'ETHIOPIC SYLLABLE KYA', +11721: 'ETHIOPIC SYLLABLE KYU', +11722: 'ETHIOPIC SYLLABLE KYI', +11723: 'ETHIOPIC SYLLABLE KYAA', +11724: 'ETHIOPIC SYLLABLE KYEE', +11725: 'ETHIOPIC SYLLABLE KYE', +11726: 'ETHIOPIC SYLLABLE KYO', +11728: 'ETHIOPIC SYLLABLE XYA', +11729: 'ETHIOPIC SYLLABLE XYU', +11730: 'ETHIOPIC SYLLABLE XYI', +11731: 'ETHIOPIC SYLLABLE XYAA', +11732: 'ETHIOPIC SYLLABLE XYEE', +11733: 'ETHIOPIC SYLLABLE XYE', +11734: 'ETHIOPIC SYLLABLE XYO', +11736: 'ETHIOPIC SYLLABLE GYA', +11737: 'ETHIOPIC SYLLABLE GYU', +11738: 'ETHIOPIC SYLLABLE GYI', +11739: 'ETHIOPIC SYLLABLE GYAA', +11740: 'ETHIOPIC SYLLABLE GYEE', +11741: 'ETHIOPIC SYLLABLE GYE', +11742: 'ETHIOPIC SYLLABLE GYO', +11776: 'RIGHT ANGLE SUBSTITUTION MARKER', +11777: 'RIGHT ANGLE DOTTED SUBSTITUTION MARKER', +11778: 'LEFT SUBSTITUTION BRACKET', +11779: 'RIGHT SUBSTITUTION BRACKET', +11780: 'LEFT DOTTED SUBSTITUTION BRACKET', +11781: 'RIGHT DOTTED SUBSTITUTION BRACKET', +11782: 'RAISED INTERPOLATION MARKER', +11783: 'RAISED DOTTED INTERPOLATION MARKER', +11784: 'DOTTED TRANSPOSITION MARKER', +11785: 'LEFT TRANSPOSITION BRACKET', +11786: 'RIGHT TRANSPOSITION BRACKET', +11787: 'RAISED SQUARE', +11788: 'LEFT RAISED OMISSION BRACKET', +11789: 'RIGHT RAISED OMISSION BRACKET', +11790: 'EDITORIAL CORONIS', +11791: 'PARAGRAPHOS', +11792: 'FORKED PARAGRAPHOS', +11793: 'REVERSED FORKED PARAGRAPHOS', +11794: 'HYPODIASTOLE', +11795: 'DOTTED OBELOS', +11796: 'DOWNWARDS ANCORA', +11797: 'UPWARDS ANCORA', +11798: 'DOTTED RIGHT-POINTING ANGLE', +11799: 'DOUBLE OBLIQUE HYPHEN', +11804: 'LEFT LOW PARAPHRASE BRACKET', +11805: 'RIGHT LOW PARAPHRASE BRACKET', 11904: 'CJK RADICAL REPEAT', 11905: 'CJK RADICAL CLIFF', 11906: 'CJK RADICAL SECOND ONE', @@ -8384,6 +9542,22 @@ 12725: 'BOPOMOFO FINAL LETTER T', 12726: 'BOPOMOFO FINAL LETTER K', 12727: 'BOPOMOFO FINAL LETTER H', +12736: 'CJK STROKE T', +12737: 'CJK STROKE WG', +12738: 'CJK STROKE XG', +12739: 'CJK STROKE BXG', +12740: 'CJK STROKE SW', +12741: 'CJK STROKE HZZ', +12742: 'CJK STROKE HZG', +12743: 'CJK STROKE HP', +12744: 'CJK STROKE HZWG', +12745: 'CJK STROKE SZWG', +12746: 'CJK STROKE HZT', +12747: 'CJK STROKE HZZP', +12748: 'CJK STROKE HPWG', +12749: 'CJK STROKE HZW', +12750: 'CJK STROKE HZZZ', +12751: 'CJK STROKE N', 12784: 'KATAKANA LETTER SMALL KU', 12785: 'KATAKANA LETTER SMALL SI', 12786: 'KATAKANA LETTER SMALL SU', @@ -8429,6 +9603,8 @@ 12826: 'PARENTHESIZED HANGUL PHIEUPH A', 12827: 'PARENTHESIZED HANGUL HIEUH A', 12828: 'PARENTHESIZED HANGUL CIEUC U', +12829: 'PARENTHESIZED KOREAN CHARACTER OJEON', +12830: 'PARENTHESIZED KOREAN CHARACTER O HU', 12832: 'PARENTHESIZED IDEOGRAPH ONE', 12833: 'PARENTHESIZED IDEOGRAPH TWO', 12834: 'PARENTHESIZED IDEOGRAPH THREE', @@ -8465,6 +9641,7 @@ 12865: 'PARENTHESIZED IDEOGRAPH REST', 12866: 'PARENTHESIZED IDEOGRAPH SELF', 12867: 'PARENTHESIZED IDEOGRAPH REACH', +12880: 'PARTNERSHIP SIGN', 12881: 'CIRCLED NUMBER TWENTY ONE', 12882: 'CIRCLED NUMBER TWENTY TWO', 12883: 'CIRCLED NUMBER TWENTY THREE', @@ -8508,6 +9685,9 @@ 12921: 'CIRCLED HANGUL THIEUTH A', 12922: 'CIRCLED HANGUL PHIEUPH A', 12923: 'CIRCLED HANGUL HIEUH A', +12924: 'CIRCLED KOREAN CHARACTER CHAMKO', +12925: 'CIRCLED KOREAN CHARACTER JUEUI', +12926: 'CIRCLED HANGUL IEUNG U', 12927: 'KOREAN STANDARD SYMBOL', 12928: 'CIRCLED IDEOGRAPH ONE', 12929: 'CIRCLED IDEOGRAPH TWO', @@ -8585,6 +9765,10 @@ 13001: 'IDEOGRAPHIC TELEGRAPH SYMBOL FOR OCTOBER', 13002: 'IDEOGRAPHIC TELEGRAPH SYMBOL FOR NOVEMBER', 13003: 'IDEOGRAPHIC TELEGRAPH SYMBOL FOR DECEMBER', +13004: 'SQUARE HG', +13005: 'SQUARE ERG', +13006: 'SQUARE EV', +13007: 'LIMITED LIABILITY SIGN', 13008: 'CIRCLED KATAKANA A', 13009: 'CIRCLED KATAKANA I', 13010: 'CIRCLED KATAKANA U', @@ -8751,6 +9935,10 @@ 13172: 'SQUARE BAR', 13173: 'SQUARE OV', 13174: 'SQUARE PC', +13175: 'SQUARE DM', +13176: 'SQUARE DM SQUARED', +13177: 'SQUARE DM CUBED', +13178: 'SQUARE IU', 13179: 'SQUARE ERA NAME HEISEI', 13180: 'SQUARE ERA NAME SYOUWA', 13181: 'SQUARE ERA NAME TAISYOU', @@ -8850,6 +10038,8 @@ 13275: 'SQUARE SR', 13276: 'SQUARE SV', 13277: 'SQUARE WB', +13278: 'SQUARE V OVER M', +13279: 'SQUARE A OVER M', 13280: 'IDEOGRAPHIC TELEGRAPH SYMBOL FOR DAY ONE', 13281: 'IDEOGRAPHIC TELEGRAPH SYMBOL FOR DAY TWO', 13282: 'IDEOGRAPHIC TELEGRAPH SYMBOL FOR DAY THREE', @@ -8881,6 +10071,71 @@ 13308: 'IDEOGRAPHIC TELEGRAPH SYMBOL FOR DAY TWENTY-NINE', 13309: 'IDEOGRAPHIC TELEGRAPH SYMBOL FOR DAY THIRTY', 13310: 'IDEOGRAPHIC TELEGRAPH SYMBOL FOR DAY THIRTY-ONE', +13311: 'SQUARE GAL', +19904: 'HEXAGRAM FOR THE CREATIVE HEAVEN', +19905: 'HEXAGRAM FOR THE RECEPTIVE EARTH', +19906: 'HEXAGRAM FOR DIFFICULTY AT THE BEGINNING', +19907: 'HEXAGRAM FOR YOUTHFUL FOLLY', +19908: 'HEXAGRAM FOR WAITING', +19909: 'HEXAGRAM FOR CONFLICT', +19910: 'HEXAGRAM FOR THE ARMY', +19911: 'HEXAGRAM FOR HOLDING TOGETHER', +19912: 'HEXAGRAM FOR SMALL TAMING', +19913: 'HEXAGRAM FOR TREADING', +19914: 'HEXAGRAM FOR PEACE', +19915: 'HEXAGRAM FOR STANDSTILL', +19916: 'HEXAGRAM FOR FELLOWSHIP', +19917: 'HEXAGRAM FOR GREAT POSSESSION', +19918: 'HEXAGRAM FOR MODESTY', +19919: 'HEXAGRAM FOR ENTHUSIASM', +19920: 'HEXAGRAM FOR FOLLOWING', +19921: 'HEXAGRAM FOR WORK ON THE DECAYED', +19922: 'HEXAGRAM FOR APPROACH', +19923: 'HEXAGRAM FOR CONTEMPLATION', +19924: 'HEXAGRAM FOR BITING THROUGH', +19925: 'HEXAGRAM FOR GRACE', +19926: 'HEXAGRAM FOR SPLITTING APART', +19927: 'HEXAGRAM FOR RETURN', +19928: 'HEXAGRAM FOR INNOCENCE', +19929: 'HEXAGRAM FOR GREAT TAMING', +19930: 'HEXAGRAM FOR MOUTH CORNERS', +19931: 'HEXAGRAM FOR GREAT PREPONDERANCE', +19932: 'HEXAGRAM FOR THE ABYSMAL WATER', +19933: 'HEXAGRAM FOR THE CLINGING FIRE', +19934: 'HEXAGRAM FOR INFLUENCE', +19935: 'HEXAGRAM FOR DURATION', +19936: 'HEXAGRAM FOR RETREAT', +19937: 'HEXAGRAM FOR GREAT POWER', +19938: 'HEXAGRAM FOR PROGRESS', +19939: 'HEXAGRAM FOR DARKENING OF THE LIGHT', +19940: 'HEXAGRAM FOR THE FAMILY', +19941: 'HEXAGRAM FOR OPPOSITION', +19942: 'HEXAGRAM FOR OBSTRUCTION', +19943: 'HEXAGRAM FOR DELIVERANCE', +19944: 'HEXAGRAM FOR DECREASE', +19945: 'HEXAGRAM FOR INCREASE', +19946: 'HEXAGRAM FOR BREAKTHROUGH', +19947: 'HEXAGRAM FOR COMING TO MEET', +19948: 'HEXAGRAM FOR GATHERING TOGETHER', +19949: 'HEXAGRAM FOR PUSHING UPWARD', +19950: 'HEXAGRAM FOR OPPRESSION', +19951: 'HEXAGRAM FOR THE WELL', +19952: 'HEXAGRAM FOR REVOLUTION', +19953: 'HEXAGRAM FOR THE CAULDRON', +19954: 'HEXAGRAM FOR THE AROUSING THUNDER', +19955: 'HEXAGRAM FOR THE KEEPING STILL MOUNTAIN', +19956: 'HEXAGRAM FOR DEVELOPMENT', +19957: 'HEXAGRAM FOR THE MARRYING MAIDEN', +19958: 'HEXAGRAM FOR ABUNDANCE', +19959: 'HEXAGRAM FOR THE WANDERER', +19960: 'HEXAGRAM FOR THE GENTLE WIND', +19961: 'HEXAGRAM FOR THE JOYOUS LAKE', +19962: 'HEXAGRAM FOR DISPERSION', +19963: 'HEXAGRAM FOR LIMITATION', +19964: 'HEXAGRAM FOR INNER TRUTH', +19965: 'HEXAGRAM FOR SMALL PREPONDERANCE', +19966: 'HEXAGRAM FOR AFTER COMPLETION', +19967: 'HEXAGRAM FOR BEFORE COMPLETION', 40960: 'YI SYLLABLE IT', 40961: 'YI SYLLABLE IX', 40962: 'YI SYLLABLE I', @@ -10101,6 +11356,73 @@ 42180: 'YI RADICAL ZZIET', 42181: 'YI RADICAL NBIE', 42182: 'YI RADICAL KE', +42752: 'MODIFIER LETTER CHINESE TONE YIN PING', +42753: 'MODIFIER LETTER CHINESE TONE YANG PING', +42754: 'MODIFIER LETTER CHINESE TONE YIN SHANG', +42755: 'MODIFIER LETTER CHINESE TONE YANG SHANG', +42756: 'MODIFIER LETTER CHINESE TONE YIN QU', +42757: 'MODIFIER LETTER CHINESE TONE YANG QU', +42758: 'MODIFIER LETTER CHINESE TONE YIN RU', +42759: 'MODIFIER LETTER CHINESE TONE YANG RU', +42760: 'MODIFIER LETTER EXTRA-HIGH DOTTED TONE BAR', +42761: 'MODIFIER LETTER HIGH DOTTED TONE BAR', +42762: 'MODIFIER LETTER MID DOTTED TONE BAR', +42763: 'MODIFIER LETTER LOW DOTTED TONE BAR', +42764: 'MODIFIER LETTER EXTRA-LOW DOTTED TONE BAR', +42765: 'MODIFIER LETTER EXTRA-HIGH DOTTED LEFT-STEM TONE BAR', +42766: 'MODIFIER LETTER HIGH DOTTED LEFT-STEM TONE BAR', +42767: 'MODIFIER LETTER MID DOTTED LEFT-STEM TONE BAR', +42768: 'MODIFIER LETTER LOW DOTTED LEFT-STEM TONE BAR', +42769: 'MODIFIER LETTER EXTRA-LOW DOTTED LEFT-STEM TONE BAR', +42770: 'MODIFIER LETTER EXTRA-HIGH LEFT-STEM TONE BAR', +42771: 'MODIFIER LETTER HIGH LEFT-STEM TONE BAR', +42772: 'MODIFIER LETTER MID LEFT-STEM TONE BAR', +42773: 'MODIFIER LETTER LOW LEFT-STEM TONE BAR', +42774: 'MODIFIER LETTER EXTRA-LOW LEFT-STEM TONE BAR', +43008: 'SYLOTI NAGRI LETTER A', +43009: 'SYLOTI NAGRI LETTER I', +43010: 'SYLOTI NAGRI SIGN DVISVARA', +43011: 'SYLOTI NAGRI LETTER U', +43012: 'SYLOTI NAGRI LETTER E', +43013: 'SYLOTI NAGRI LETTER O', +43014: 'SYLOTI NAGRI SIGN HASANTA', +43015: 'SYLOTI NAGRI LETTER KO', +43016: 'SYLOTI NAGRI LETTER KHO', +43017: 'SYLOTI NAGRI LETTER GO', +43018: 'SYLOTI NAGRI LETTER GHO', +43019: 'SYLOTI NAGRI SIGN ANUSVARA', +43020: 'SYLOTI NAGRI LETTER CO', +43021: 'SYLOTI NAGRI LETTER CHO', +43022: 'SYLOTI NAGRI LETTER JO', +43023: 'SYLOTI NAGRI LETTER JHO', +43024: 'SYLOTI NAGRI LETTER TTO', +43025: 'SYLOTI NAGRI LETTER TTHO', +43026: 'SYLOTI NAGRI LETTER DDO', +43027: 'SYLOTI NAGRI LETTER DDHO', +43028: 'SYLOTI NAGRI LETTER TO', +43029: 'SYLOTI NAGRI LETTER THO', +43030: 'SYLOTI NAGRI LETTER DO', +43031: 'SYLOTI NAGRI LETTER DHO', +43032: 'SYLOTI NAGRI LETTER NO', +43033: 'SYLOTI NAGRI LETTER PO', +43034: 'SYLOTI NAGRI LETTER PHO', +43035: 'SYLOTI NAGRI LETTER BO', +43036: 'SYLOTI NAGRI LETTER BHO', +43037: 'SYLOTI NAGRI LETTER MO', +43038: 'SYLOTI NAGRI LETTER RO', +43039: 'SYLOTI NAGRI LETTER LO', +43040: 'SYLOTI NAGRI LETTER RRO', +43041: 'SYLOTI NAGRI LETTER SO', +43042: 'SYLOTI NAGRI LETTER HO', +43043: 'SYLOTI NAGRI VOWEL SIGN A', +43044: 'SYLOTI NAGRI VOWEL SIGN I', +43045: 'SYLOTI NAGRI VOWEL SIGN U', +43046: 'SYLOTI NAGRI VOWEL SIGN E', +43047: 'SYLOTI NAGRI VOWEL SIGN OO', +43048: 'SYLOTI NAGRI POETRY MARK-1', +43049: 'SYLOTI NAGRI POETRY MARK-2', +43050: 'SYLOTI NAGRI POETRY MARK-3', +43051: 'SYLOTI NAGRI POETRY MARK-4', 63744: 'CJK COMPATIBILITY IDEOGRAPH-F900', 63745: 'CJK COMPATIBILITY IDEOGRAPH-F901', 63746: 'CJK COMPATIBILITY IDEOGRAPH-F902', @@ -10462,6 +11784,112 @@ 64104: 'CJK COMPATIBILITY IDEOGRAPH-FA68', 64105: 'CJK COMPATIBILITY IDEOGRAPH-FA69', 64106: 'CJK COMPATIBILITY IDEOGRAPH-FA6A', +64112: 'CJK COMPATIBILITY IDEOGRAPH-FA70', +64113: 'CJK COMPATIBILITY IDEOGRAPH-FA71', +64114: 'CJK COMPATIBILITY IDEOGRAPH-FA72', +64115: 'CJK COMPATIBILITY IDEOGRAPH-FA73', +64116: 'CJK COMPATIBILITY IDEOGRAPH-FA74', +64117: 'CJK COMPATIBILITY IDEOGRAPH-FA75', +64118: 'CJK COMPATIBILITY IDEOGRAPH-FA76', +64119: 'CJK COMPATIBILITY IDEOGRAPH-FA77', +64120: 'CJK COMPATIBILITY IDEOGRAPH-FA78', +64121: 'CJK COMPATIBILITY IDEOGRAPH-FA79', +64122: 'CJK COMPATIBILITY IDEOGRAPH-FA7A', +64123: 'CJK COMPATIBILITY IDEOGRAPH-FA7B', +64124: 'CJK COMPATIBILITY IDEOGRAPH-FA7C', +64125: 'CJK COMPATIBILITY IDEOGRAPH-FA7D', +64126: 'CJK COMPATIBILITY IDEOGRAPH-FA7E', +64127: 'CJK COMPATIBILITY IDEOGRAPH-FA7F', +64128: 'CJK COMPATIBILITY IDEOGRAPH-FA80', +64129: 'CJK COMPATIBILITY IDEOGRAPH-FA81', +64130: 'CJK COMPATIBILITY IDEOGRAPH-FA82', +64131: 'CJK COMPATIBILITY IDEOGRAPH-FA83', +64132: 'CJK COMPATIBILITY IDEOGRAPH-FA84', +64133: 'CJK COMPATIBILITY IDEOGRAPH-FA85', +64134: 'CJK COMPATIBILITY IDEOGRAPH-FA86', +64135: 'CJK COMPATIBILITY IDEOGRAPH-FA87', +64136: 'CJK COMPATIBILITY IDEOGRAPH-FA88', +64137: 'CJK COMPATIBILITY IDEOGRAPH-FA89', +64138: 'CJK COMPATIBILITY IDEOGRAPH-FA8A', +64139: 'CJK COMPATIBILITY IDEOGRAPH-FA8B', +64140: 'CJK COMPATIBILITY IDEOGRAPH-FA8C', +64141: 'CJK COMPATIBILITY IDEOGRAPH-FA8D', +64142: 'CJK COMPATIBILITY IDEOGRAPH-FA8E', +64143: 'CJK COMPATIBILITY IDEOGRAPH-FA8F', +64144: 'CJK COMPATIBILITY IDEOGRAPH-FA90', +64145: 'CJK COMPATIBILITY IDEOGRAPH-FA91', +64146: 'CJK COMPATIBILITY IDEOGRAPH-FA92', +64147: 'CJK COMPATIBILITY IDEOGRAPH-FA93', +64148: 'CJK COMPATIBILITY IDEOGRAPH-FA94', +64149: 'CJK COMPATIBILITY IDEOGRAPH-FA95', +64150: 'CJK COMPATIBILITY IDEOGRAPH-FA96', +64151: 'CJK COMPATIBILITY IDEOGRAPH-FA97', +64152: 'CJK COMPATIBILITY IDEOGRAPH-FA98', +64153: 'CJK COMPATIBILITY IDEOGRAPH-FA99', +64154: 'CJK COMPATIBILITY IDEOGRAPH-FA9A', +64155: 'CJK COMPATIBILITY IDEOGRAPH-FA9B', +64156: 'CJK COMPATIBILITY IDEOGRAPH-FA9C', +64157: 'CJK COMPATIBILITY IDEOGRAPH-FA9D', +64158: 'CJK COMPATIBILITY IDEOGRAPH-FA9E', +64159: 'CJK COMPATIBILITY IDEOGRAPH-FA9F', +64160: 'CJK COMPATIBILITY IDEOGRAPH-FAA0', +64161: 'CJK COMPATIBILITY IDEOGRAPH-FAA1', +64162: 'CJK COMPATIBILITY IDEOGRAPH-FAA2', +64163: 'CJK COMPATIBILITY IDEOGRAPH-FAA3', +64164: 'CJK COMPATIBILITY IDEOGRAPH-FAA4', +64165: 'CJK COMPATIBILITY IDEOGRAPH-FAA5', +64166: 'CJK COMPATIBILITY IDEOGRAPH-FAA6', +64167: 'CJK COMPATIBILITY IDEOGRAPH-FAA7', +64168: 'CJK COMPATIBILITY IDEOGRAPH-FAA8', +64169: 'CJK COMPATIBILITY IDEOGRAPH-FAA9', +64170: 'CJK COMPATIBILITY IDEOGRAPH-FAAA', +64171: 'CJK COMPATIBILITY IDEOGRAPH-FAAB', +64172: 'CJK COMPATIBILITY IDEOGRAPH-FAAC', +64173: 'CJK COMPATIBILITY IDEOGRAPH-FAAD', +64174: 'CJK COMPATIBILITY IDEOGRAPH-FAAE', +64175: 'CJK COMPATIBILITY IDEOGRAPH-FAAF', +64176: 'CJK COMPATIBILITY IDEOGRAPH-FAB0', +64177: 'CJK COMPATIBILITY IDEOGRAPH-FAB1', +64178: 'CJK COMPATIBILITY IDEOGRAPH-FAB2', +64179: 'CJK COMPATIBILITY IDEOGRAPH-FAB3', +64180: 'CJK COMPATIBILITY IDEOGRAPH-FAB4', +64181: 'CJK COMPATIBILITY IDEOGRAPH-FAB5', +64182: 'CJK COMPATIBILITY IDEOGRAPH-FAB6', +64183: 'CJK COMPATIBILITY IDEOGRAPH-FAB7', +64184: 'CJK COMPATIBILITY IDEOGRAPH-FAB8', +64185: 'CJK COMPATIBILITY IDEOGRAPH-FAB9', +64186: 'CJK COMPATIBILITY IDEOGRAPH-FABA', +64187: 'CJK COMPATIBILITY IDEOGRAPH-FABB', +64188: 'CJK COMPATIBILITY IDEOGRAPH-FABC', +64189: 'CJK COMPATIBILITY IDEOGRAPH-FABD', +64190: 'CJK COMPATIBILITY IDEOGRAPH-FABE', +64191: 'CJK COMPATIBILITY IDEOGRAPH-FABF', +64192: 'CJK COMPATIBILITY IDEOGRAPH-FAC0', +64193: 'CJK COMPATIBILITY IDEOGRAPH-FAC1', +64194: 'CJK COMPATIBILITY IDEOGRAPH-FAC2', +64195: 'CJK COMPATIBILITY IDEOGRAPH-FAC3', +64196: 'CJK COMPATIBILITY IDEOGRAPH-FAC4', +64197: 'CJK COMPATIBILITY IDEOGRAPH-FAC5', +64198: 'CJK COMPATIBILITY IDEOGRAPH-FAC6', +64199: 'CJK COMPATIBILITY IDEOGRAPH-FAC7', +64200: 'CJK COMPATIBILITY IDEOGRAPH-FAC8', +64201: 'CJK COMPATIBILITY IDEOGRAPH-FAC9', +64202: 'CJK COMPATIBILITY IDEOGRAPH-FACA', +64203: 'CJK COMPATIBILITY IDEOGRAPH-FACB', +64204: 'CJK COMPATIBILITY IDEOGRAPH-FACC', +64205: 'CJK COMPATIBILITY IDEOGRAPH-FACD', +64206: 'CJK COMPATIBILITY IDEOGRAPH-FACE', +64207: 'CJK COMPATIBILITY IDEOGRAPH-FACF', +64208: 'CJK COMPATIBILITY IDEOGRAPH-FAD0', +64209: 'CJK COMPATIBILITY IDEOGRAPH-FAD1', +64210: 'CJK COMPATIBILITY IDEOGRAPH-FAD2', +64211: 'CJK COMPATIBILITY IDEOGRAPH-FAD3', +64212: 'CJK COMPATIBILITY IDEOGRAPH-FAD4', +64213: 'CJK COMPATIBILITY IDEOGRAPH-FAD5', +64214: 'CJK COMPATIBILITY IDEOGRAPH-FAD6', +64215: 'CJK COMPATIBILITY IDEOGRAPH-FAD7', +64216: 'CJK COMPATIBILITY IDEOGRAPH-FAD8', +64217: 'CJK COMPATIBILITY IDEOGRAPH-FAD9', 64256: 'LATIN SMALL LIGATURE FF', 64257: 'LATIN SMALL LIGATURE FI', 64258: 'LATIN SMALL LIGATURE FL', @@ -11114,6 +12542,7 @@ 65018: 'ARABIC LIGATURE SALLALLAHOU ALAYHE WASALLAM', 65019: 'ARABIC LIGATURE JALLAJALALOUHOU', 65020: 'RIAL SIGN', +65021: 'ARABIC LIGATURE BISMILLAH AR-RAHMAN AR-RAHEEM', 65024: 'VARIATION SELECTOR-1', 65025: 'VARIATION SELECTOR-2', 65026: 'VARIATION SELECTOR-3', @@ -11130,6 +12559,16 @@ 65037: 'VARIATION SELECTOR-14', 65038: 'VARIATION SELECTOR-15', 65039: 'VARIATION SELECTOR-16', +65040: 'PRESENTATION FORM FOR VERTICAL COMMA', +65041: 'PRESENTATION FORM FOR VERTICAL IDEOGRAPHIC COMMA', +65042: 'PRESENTATION FORM FOR VERTICAL IDEOGRAPHIC FULL STOP', +65043: 'PRESENTATION FORM FOR VERTICAL COLON', +65044: 'PRESENTATION FORM FOR VERTICAL SEMICOLON', +65045: 'PRESENTATION FORM FOR VERTICAL EXCLAMATION MARK', +65046: 'PRESENTATION FORM FOR VERTICAL QUESTION MARK', +65047: 'PRESENTATION FORM FOR VERTICAL LEFT WHITE LENTICULAR BRACKET', +65048: 'PRESENTATION FORM FOR VERTICAL RIGHT WHITE LENTICULAR BRAKCET', +65049: 'PRESENTATION FORM FOR VERTICAL HORIZONTAL ELLIPSIS', 65056: 'COMBINING LIGATURE LEFT HALF', 65057: 'COMBINING LIGATURE RIGHT HALF', 65058: 'COMBINING DOUBLE TILDE LEFT HALF', @@ -11157,6 +12596,8 @@ 65092: 'PRESENTATION FORM FOR VERTICAL RIGHT WHITE CORNER BRACKET', 65093: 'SESAME DOT', 65094: 'WHITE SESAME DOT', +65095: 'PRESENTATION FORM FOR VERTICAL LEFT SQUARE BRACKET', +65096: 'PRESENTATION FORM FOR VERTICAL RIGHT SQUARE BRACKET', 65097: 'DASHED OVERLINE', 65098: 'CENTRELINE OVERLINE', 65099: 'WAVY OVERLINE', @@ -11561,6 +13002,349 @@ 65531: 'INTERLINEAR ANNOTATION TERMINATOR', 65532: 'OBJECT REPLACEMENT CHARACTER', 65533: 'REPLACEMENT CHARACTER', +65536: 'LINEAR B SYLLABLE B008 A', +65537: 'LINEAR B SYLLABLE B038 E', +65538: 'LINEAR B SYLLABLE B028 I', +65539: 'LINEAR B SYLLABLE B061 O', +65540: 'LINEAR B SYLLABLE B010 U', +65541: 'LINEAR B SYLLABLE B001 DA', +65542: 'LINEAR B SYLLABLE B045 DE', +65543: 'LINEAR B SYLLABLE B007 DI', +65544: 'LINEAR B SYLLABLE B014 DO', +65545: 'LINEAR B SYLLABLE B051 DU', +65546: 'LINEAR B SYLLABLE B057 JA', +65547: 'LINEAR B SYLLABLE B046 JE', +65549: 'LINEAR B SYLLABLE B036 JO', +65550: 'LINEAR B SYLLABLE B065 JU', +65551: 'LINEAR B SYLLABLE B077 KA', +65552: 'LINEAR B SYLLABLE B044 KE', +65553: 'LINEAR B SYLLABLE B067 KI', +65554: 'LINEAR B SYLLABLE B070 KO', +65555: 'LINEAR B SYLLABLE B081 KU', +65556: 'LINEAR B SYLLABLE B080 MA', +65557: 'LINEAR B SYLLABLE B013 ME', +65558: 'LINEAR B SYLLABLE B073 MI', +65559: 'LINEAR B SYLLABLE B015 MO', +65560: 'LINEAR B SYLLABLE B023 MU', +65561: 'LINEAR B SYLLABLE B006 NA', +65562: 'LINEAR B SYLLABLE B024 NE', +65563: 'LINEAR B SYLLABLE B030 NI', +65564: 'LINEAR B SYLLABLE B052 NO', +65565: 'LINEAR B SYLLABLE B055 NU', +65566: 'LINEAR B SYLLABLE B003 PA', +65567: 'LINEAR B SYLLABLE B072 PE', +65568: 'LINEAR B SYLLABLE B039 PI', +65569: 'LINEAR B SYLLABLE B011 PO', +65570: 'LINEAR B SYLLABLE B050 PU', +65571: 'LINEAR B SYLLABLE B016 QA', +65572: 'LINEAR B SYLLABLE B078 QE', +65573: 'LINEAR B SYLLABLE B021 QI', +65574: 'LINEAR B SYLLABLE B032 QO', +65576: 'LINEAR B SYLLABLE B060 RA', +65577: 'LINEAR B SYLLABLE B027 RE', +65578: 'LINEAR B SYLLABLE B053 RI', +65579: 'LINEAR B SYLLABLE B002 RO', +65580: 'LINEAR B SYLLABLE B026 RU', +65581: 'LINEAR B SYLLABLE B031 SA', +65582: 'LINEAR B SYLLABLE B009 SE', +65583: 'LINEAR B SYLLABLE B041 SI', +65584: 'LINEAR B SYLLABLE B012 SO', +65585: 'LINEAR B SYLLABLE B058 SU', +65586: 'LINEAR B SYLLABLE B059 TA', +65587: 'LINEAR B SYLLABLE B004 TE', +65588: 'LINEAR B SYLLABLE B037 TI', +65589: 'LINEAR B SYLLABLE B005 TO', +65590: 'LINEAR B SYLLABLE B069 TU', +65591: 'LINEAR B SYLLABLE B054 WA', +65592: 'LINEAR B SYLLABLE B075 WE', +65593: 'LINEAR B SYLLABLE B040 WI', +65594: 'LINEAR B SYLLABLE B042 WO', +65596: 'LINEAR B SYLLABLE B017 ZA', +65597: 'LINEAR B SYLLABLE B074 ZE', +65599: 'LINEAR B SYLLABLE B020 ZO', +65600: 'LINEAR B SYLLABLE B025 A2', +65601: 'LINEAR B SYLLABLE B043 A3', +65602: 'LINEAR B SYLLABLE B085 AU', +65603: 'LINEAR B SYLLABLE B071 DWE', +65604: 'LINEAR B SYLLABLE B090 DWO', +65605: 'LINEAR B SYLLABLE B048 NWA', +65606: 'LINEAR B SYLLABLE B029 PU2', +65607: 'LINEAR B SYLLABLE B062 PTE', +65608: 'LINEAR B SYLLABLE B076 RA2', +65609: 'LINEAR B SYLLABLE B033 RA3', +65610: 'LINEAR B SYLLABLE B068 RO2', +65611: 'LINEAR B SYLLABLE B066 TA2', +65612: 'LINEAR B SYLLABLE B087 TWE', +65613: 'LINEAR B SYLLABLE B091 TWO', +65616: 'LINEAR B SYMBOL B018', +65617: 'LINEAR B SYMBOL B019', +65618: 'LINEAR B SYMBOL B022', +65619: 'LINEAR B SYMBOL B034', +65620: 'LINEAR B SYMBOL B047', +65621: 'LINEAR B SYMBOL B049', +65622: 'LINEAR B SYMBOL B056', +65623: 'LINEAR B SYMBOL B063', +65624: 'LINEAR B SYMBOL B064', +65625: 'LINEAR B SYMBOL B079', +65626: 'LINEAR B SYMBOL B082', +65627: 'LINEAR B SYMBOL B083', +65628: 'LINEAR B SYMBOL B086', +65629: 'LINEAR B SYMBOL B089', +65664: 'LINEAR B IDEOGRAM B100 MAN', +65665: 'LINEAR B IDEOGRAM B102 WOMAN', +65666: 'LINEAR B IDEOGRAM B104 DEER', +65667: 'LINEAR B IDEOGRAM B105 EQUID', +65668: 'LINEAR B IDEOGRAM B105F MARE', +65669: 'LINEAR B IDEOGRAM B105M STALLION', +65670: 'LINEAR B IDEOGRAM B106F EWE', +65671: 'LINEAR B IDEOGRAM B106M RAM', +65672: 'LINEAR B IDEOGRAM B107F SHE-GOAT', +65673: 'LINEAR B IDEOGRAM B107M HE-GOAT', +65674: 'LINEAR B IDEOGRAM B108F SOW', +65675: 'LINEAR B IDEOGRAM B108M BOAR', +65676: 'LINEAR B IDEOGRAM B109F COW', +65677: 'LINEAR B IDEOGRAM B109M BULL', +65678: 'LINEAR B IDEOGRAM B120 WHEAT', +65679: 'LINEAR B IDEOGRAM B121 BARLEY', +65680: 'LINEAR B IDEOGRAM B122 OLIVE', +65681: 'LINEAR B IDEOGRAM B123 SPICE', +65682: 'LINEAR B IDEOGRAM B125 CYPERUS', +65683: 'LINEAR B MONOGRAM B127 KAPO', +65684: 'LINEAR B MONOGRAM B128 KANAKO', +65685: 'LINEAR B IDEOGRAM B130 OIL', +65686: 'LINEAR B IDEOGRAM B131 WINE', +65687: 'LINEAR B IDEOGRAM B132', +65688: 'LINEAR B MONOGRAM B133 AREPA', +65689: 'LINEAR B MONOGRAM B135 MERI', +65690: 'LINEAR B IDEOGRAM B140 BRONZE', +65691: 'LINEAR B IDEOGRAM B141 GOLD', +65692: 'LINEAR B IDEOGRAM B142', +65693: 'LINEAR B IDEOGRAM B145 WOOL', +65694: 'LINEAR B IDEOGRAM B146', +65695: 'LINEAR B IDEOGRAM B150', +65696: 'LINEAR B IDEOGRAM B151 HORN', +65697: 'LINEAR B IDEOGRAM B152', +65698: 'LINEAR B IDEOGRAM B153', +65699: 'LINEAR B IDEOGRAM B154', +65700: 'LINEAR B MONOGRAM B156 TURO2', +65701: 'LINEAR B IDEOGRAM B157', +65702: 'LINEAR B IDEOGRAM B158', +65703: 'LINEAR B IDEOGRAM B159 CLOTH', +65704: 'LINEAR B IDEOGRAM B160', +65705: 'LINEAR B IDEOGRAM B161', +65706: 'LINEAR B IDEOGRAM B162 GARMENT', +65707: 'LINEAR B IDEOGRAM B163 ARMOUR', +65708: 'LINEAR B IDEOGRAM B164', +65709: 'LINEAR B IDEOGRAM B165', +65710: 'LINEAR B IDEOGRAM B166', +65711: 'LINEAR B IDEOGRAM B167', +65712: 'LINEAR B IDEOGRAM B168', +65713: 'LINEAR B IDEOGRAM B169', +65714: 'LINEAR B IDEOGRAM B170', +65715: 'LINEAR B IDEOGRAM B171', +65716: 'LINEAR B IDEOGRAM B172', +65717: 'LINEAR B IDEOGRAM B173 MONTH', +65718: 'LINEAR B IDEOGRAM B174', +65719: 'LINEAR B IDEOGRAM B176 TREE', +65720: 'LINEAR B IDEOGRAM B177', +65721: 'LINEAR B IDEOGRAM B178', +65722: 'LINEAR B IDEOGRAM B179', +65723: 'LINEAR B IDEOGRAM B180', +65724: 'LINEAR B IDEOGRAM B181', +65725: 'LINEAR B IDEOGRAM B182', +65726: 'LINEAR B IDEOGRAM B183', +65727: 'LINEAR B IDEOGRAM B184', +65728: 'LINEAR B IDEOGRAM B185', +65729: 'LINEAR B IDEOGRAM B189', +65730: 'LINEAR B IDEOGRAM B190', +65731: 'LINEAR B IDEOGRAM B191 HELMET', +65732: 'LINEAR B IDEOGRAM B220 FOOTSTOOL', +65733: 'LINEAR B IDEOGRAM B225 BATHTUB', +65734: 'LINEAR B IDEOGRAM B230 SPEAR', +65735: 'LINEAR B IDEOGRAM B231 ARROW', +65736: 'LINEAR B IDEOGRAM B232', +65737: 'LINEAR B IDEOGRAM B233 SWORD', +65738: 'LINEAR B IDEOGRAM B234', +65739: 'LINEAR B IDEOGRAM B236', +65740: 'LINEAR B IDEOGRAM B240 WHEELED CHARIOT', +65741: 'LINEAR B IDEOGRAM B241 CHARIOT', +65742: 'LINEAR B IDEOGRAM B242 CHARIOT FRAME', +65743: 'LINEAR B IDEOGRAM B243 WHEEL', +65744: 'LINEAR B IDEOGRAM B245', +65745: 'LINEAR B IDEOGRAM B246', +65746: 'LINEAR B MONOGRAM B247 DIPTE', +65747: 'LINEAR B IDEOGRAM B248', +65748: 'LINEAR B IDEOGRAM B249', +65749: 'LINEAR B IDEOGRAM B251', +65750: 'LINEAR B IDEOGRAM B252', +65751: 'LINEAR B IDEOGRAM B253', +65752: 'LINEAR B IDEOGRAM B254 DART', +65753: 'LINEAR B IDEOGRAM B255', +65754: 'LINEAR B IDEOGRAM B256', +65755: 'LINEAR B IDEOGRAM B257', +65756: 'LINEAR B IDEOGRAM B258', +65757: 'LINEAR B IDEOGRAM B259', +65758: 'LINEAR B IDEOGRAM VESSEL B155', +65759: 'LINEAR B IDEOGRAM VESSEL B200', +65760: 'LINEAR B IDEOGRAM VESSEL B201', +65761: 'LINEAR B IDEOGRAM VESSEL B202', +65762: 'LINEAR B IDEOGRAM VESSEL B203', +65763: 'LINEAR B IDEOGRAM VESSEL B204', +65764: 'LINEAR B IDEOGRAM VESSEL B205', +65765: 'LINEAR B IDEOGRAM VESSEL B206', +65766: 'LINEAR B IDEOGRAM VESSEL B207', +65767: 'LINEAR B IDEOGRAM VESSEL B208', +65768: 'LINEAR B IDEOGRAM VESSEL B209', +65769: 'LINEAR B IDEOGRAM VESSEL B210', +65770: 'LINEAR B IDEOGRAM VESSEL B211', +65771: 'LINEAR B IDEOGRAM VESSEL B212', +65772: 'LINEAR B IDEOGRAM VESSEL B213', +65773: 'LINEAR B IDEOGRAM VESSEL B214', +65774: 'LINEAR B IDEOGRAM VESSEL B215', +65775: 'LINEAR B IDEOGRAM VESSEL B216', +65776: 'LINEAR B IDEOGRAM VESSEL B217', +65777: 'LINEAR B IDEOGRAM VESSEL B218', +65778: 'LINEAR B IDEOGRAM VESSEL B219', +65779: 'LINEAR B IDEOGRAM VESSEL B221', +65780: 'LINEAR B IDEOGRAM VESSEL B222', +65781: 'LINEAR B IDEOGRAM VESSEL B226', +65782: 'LINEAR B IDEOGRAM VESSEL B227', +65783: 'LINEAR B IDEOGRAM VESSEL B228', +65784: 'LINEAR B IDEOGRAM VESSEL B229', +65785: 'LINEAR B IDEOGRAM VESSEL B250', +65786: 'LINEAR B IDEOGRAM VESSEL B305', +65792: 'AEGEAN WORD SEPARATOR LINE', +65793: 'AEGEAN WORD SEPARATOR DOT', +65794: 'AEGEAN CHECK MARK', +65799: 'AEGEAN NUMBER ONE', +65800: 'AEGEAN NUMBER TWO', +65801: 'AEGEAN NUMBER THREE', +65802: 'AEGEAN NUMBER FOUR', +65803: 'AEGEAN NUMBER FIVE', +65804: 'AEGEAN NUMBER SIX', +65805: 'AEGEAN NUMBER SEVEN', +65806: 'AEGEAN NUMBER EIGHT', +65807: 'AEGEAN NUMBER NINE', +65808: 'AEGEAN NUMBER TEN', +65809: 'AEGEAN NUMBER TWENTY', +65810: 'AEGEAN NUMBER THIRTY', +65811: 'AEGEAN NUMBER FORTY', +65812: 'AEGEAN NUMBER FIFTY', +65813: 'AEGEAN NUMBER SIXTY', +65814: 'AEGEAN NUMBER SEVENTY', +65815: 'AEGEAN NUMBER EIGHTY', +65816: 'AEGEAN NUMBER NINETY', +65817: 'AEGEAN NUMBER ONE HUNDRED', +65818: 'AEGEAN NUMBER TWO HUNDRED', +65819: 'AEGEAN NUMBER THREE HUNDRED', +65820: 'AEGEAN NUMBER FOUR HUNDRED', +65821: 'AEGEAN NUMBER FIVE HUNDRED', +65822: 'AEGEAN NUMBER SIX HUNDRED', +65823: 'AEGEAN NUMBER SEVEN HUNDRED', +65824: 'AEGEAN NUMBER EIGHT HUNDRED', +65825: 'AEGEAN NUMBER NINE HUNDRED', +65826: 'AEGEAN NUMBER ONE THOUSAND', +65827: 'AEGEAN NUMBER TWO THOUSAND', +65828: 'AEGEAN NUMBER THREE THOUSAND', +65829: 'AEGEAN NUMBER FOUR THOUSAND', +65830: 'AEGEAN NUMBER FIVE THOUSAND', +65831: 'AEGEAN NUMBER SIX THOUSAND', +65832: 'AEGEAN NUMBER SEVEN THOUSAND', +65833: 'AEGEAN NUMBER EIGHT THOUSAND', +65834: 'AEGEAN NUMBER NINE THOUSAND', +65835: 'AEGEAN NUMBER TEN THOUSAND', +65836: 'AEGEAN NUMBER TWENTY THOUSAND', +65837: 'AEGEAN NUMBER THIRTY THOUSAND', +65838: 'AEGEAN NUMBER FORTY THOUSAND', +65839: 'AEGEAN NUMBER FIFTY THOUSAND', +65840: 'AEGEAN NUMBER SIXTY THOUSAND', +65841: 'AEGEAN NUMBER SEVENTY THOUSAND', +65842: 'AEGEAN NUMBER EIGHTY THOUSAND', +65843: 'AEGEAN NUMBER NINETY THOUSAND', +65847: 'AEGEAN WEIGHT BASE UNIT', +65848: 'AEGEAN WEIGHT FIRST SUBUNIT', +65849: 'AEGEAN WEIGHT SECOND SUBUNIT', +65850: 'AEGEAN WEIGHT THIRD SUBUNIT', +65851: 'AEGEAN WEIGHT FOURTH SUBUNIT', +65852: 'AEGEAN DRY MEASURE FIRST SUBUNIT', +65853: 'AEGEAN LIQUID MEASURE FIRST SUBUNIT', +65854: 'AEGEAN MEASURE SECOND SUBUNIT', +65855: 'AEGEAN MEASURE THIRD SUBUNIT', +65856: 'GREEK ACROPHONIC ATTIC ONE QUARTER', +65857: 'GREEK ACROPHONIC ATTIC ONE HALF', +65858: 'GREEK ACROPHONIC ATTIC ONE DRACHMA', +65859: 'GREEK ACROPHONIC ATTIC FIVE', +65860: 'GREEK ACROPHONIC ATTIC FIFTY', +65861: 'GREEK ACROPHONIC ATTIC FIVE HUNDRED', +65862: 'GREEK ACROPHONIC ATTIC FIVE THOUSAND', +65863: 'GREEK ACROPHONIC ATTIC FIFTY THOUSAND', +65864: 'GREEK ACROPHONIC ATTIC FIVE TALENTS', +65865: 'GREEK ACROPHONIC ATTIC TEN TALENTS', +65866: 'GREEK ACROPHONIC ATTIC FIFTY TALENTS', +65867: 'GREEK ACROPHONIC ATTIC ONE HUNDRED TALENTS', +65868: 'GREEK ACROPHONIC ATTIC FIVE HUNDRED TALENTS', +65869: 'GREEK ACROPHONIC ATTIC ONE THOUSAND TALENTS', +65870: 'GREEK ACROPHONIC ATTIC FIVE THOUSAND TALENTS', +65871: 'GREEK ACROPHONIC ATTIC FIVE STATERS', +65872: 'GREEK ACROPHONIC ATTIC TEN STATERS', +65873: 'GREEK ACROPHONIC ATTIC FIFTY STATERS', +65874: 'GREEK ACROPHONIC ATTIC ONE HUNDRED STATERS', +65875: 'GREEK ACROPHONIC ATTIC FIVE HUNDRED STATERS', +65876: 'GREEK ACROPHONIC ATTIC ONE THOUSAND STATERS', +65877: 'GREEK ACROPHONIC ATTIC TEN THOUSAND STATERS', +65878: 'GREEK ACROPHONIC ATTIC FIFTY THOUSAND STATERS', +65879: 'GREEK ACROPHONIC ATTIC TEN MNAS', +65880: 'GREEK ACROPHONIC HERAEUM ONE PLETHRON', +65881: 'GREEK ACROPHONIC THESPIAN ONE', +65882: 'GREEK ACROPHONIC HERMIONIAN ONE', +65883: 'GREEK ACROPHONIC EPIDAUREAN TWO', +65884: 'GREEK ACROPHONIC THESPIAN TWO', +65885: 'GREEK ACROPHONIC CYRENAIC TWO DRACHMAS', +65886: 'GREEK ACROPHONIC EPIDAUREAN TWO DRACHMAS', +65887: 'GREEK ACROPHONIC TROEZENIAN FIVE', +65888: 'GREEK ACROPHONIC TROEZENIAN TEN', +65889: 'GREEK ACROPHONIC TROEZENIAN TEN ALTERNATE FORM', +65890: 'GREEK ACROPHONIC HERMIONIAN TEN', +65891: 'GREEK ACROPHONIC MESSENIAN TEN', +65892: 'GREEK ACROPHONIC THESPIAN TEN', +65893: 'GREEK ACROPHONIC THESPIAN THIRTY', +65894: 'GREEK ACROPHONIC TROEZENIAN FIFTY', +65895: 'GREEK ACROPHONIC TROEZENIAN FIFTY ALTERNATE FORM', +65896: 'GREEK ACROPHONIC HERMIONIAN FIFTY', +65897: 'GREEK ACROPHONIC THESPIAN FIFTY', +65898: 'GREEK ACROPHONIC THESPIAN ONE HUNDRED', +65899: 'GREEK ACROPHONIC THESPIAN THREE HUNDRED', +65900: 'GREEK ACROPHONIC EPIDAUREAN FIVE HUNDRED', +65901: 'GREEK ACROPHONIC TROEZENIAN FIVE HUNDRED', +65902: 'GREEK ACROPHONIC THESPIAN FIVE HUNDRED', +65903: 'GREEK ACROPHONIC CARYSTIAN FIVE HUNDRED', +65904: 'GREEK ACROPHONIC NAXIAN FIVE HUNDRED', +65905: 'GREEK ACROPHONIC THESPIAN ONE THOUSAND', +65906: 'GREEK ACROPHONIC THESPIAN FIVE THOUSAND', +65907: 'GREEK ACROPHONIC DELPHIC FIVE MNAS', +65908: 'GREEK ACROPHONIC STRATIAN FIFTY MNAS', +65909: 'GREEK ONE HALF SIGN', +65910: 'GREEK ONE HALF SIGN ALTERNATE FORM', +65911: 'GREEK TWO THIRDS SIGN', +65912: 'GREEK THREE QUARTERS SIGN', +65913: 'GREEK YEAR SIGN', +65914: 'GREEK TALENT SIGN', +65915: 'GREEK DRACHMA SIGN', +65916: 'GREEK OBOL SIGN', +65917: 'GREEK TWO OBOLS SIGN', +65918: 'GREEK THREE OBOLS SIGN', +65919: 'GREEK FOUR OBOLS SIGN', +65920: 'GREEK FIVE OBOLS SIGN', +65921: 'GREEK METRETES SIGN', +65922: 'GREEK KYATHOS BASE SIGN', +65923: 'GREEK LITRA SIGN', +65924: 'GREEK OUNKIA SIGN', +65925: 'GREEK XESTES SIGN', +65926: 'GREEK ARTABE SIGN', +65927: 'GREEK AROURA SIGN', +65928: 'GREEK GRAMMA SIGN', +65929: 'GREEK TRYBLION BASE SIGN', +65930: 'GREEK ZERO SIGN', 66304: 'OLD ITALIC LETTER A', 66305: 'OLD ITALIC LETTER BE', 66306: 'OLD ITALIC LETTER KE', @@ -11623,6 +13407,87 @@ 66376: 'GOTHIC LETTER HWAIR', 66377: 'GOTHIC LETTER OTHAL', 66378: 'GOTHIC LETTER NINE HUNDRED', +66432: 'UGARITIC LETTER ALPA', +66433: 'UGARITIC LETTER BETA', +66434: 'UGARITIC LETTER GAMLA', +66435: 'UGARITIC LETTER KHA', +66436: 'UGARITIC LETTER DELTA', +66437: 'UGARITIC LETTER HO', +66438: 'UGARITIC LETTER WO', +66439: 'UGARITIC LETTER ZETA', +66440: 'UGARITIC LETTER HOTA', +66441: 'UGARITIC LETTER TET', +66442: 'UGARITIC LETTER YOD', +66443: 'UGARITIC LETTER KAF', +66444: 'UGARITIC LETTER SHIN', +66445: 'UGARITIC LETTER LAMDA', +66446: 'UGARITIC LETTER MEM', +66447: 'UGARITIC LETTER DHAL', +66448: 'UGARITIC LETTER NUN', +66449: 'UGARITIC LETTER ZU', +66450: 'UGARITIC LETTER SAMKA', +66451: 'UGARITIC LETTER AIN', +66452: 'UGARITIC LETTER PU', +66453: 'UGARITIC LETTER SADE', +66454: 'UGARITIC LETTER QOPA', +66455: 'UGARITIC LETTER RASHA', +66456: 'UGARITIC LETTER THANNA', +66457: 'UGARITIC LETTER GHAIN', +66458: 'UGARITIC LETTER TO', +66459: 'UGARITIC LETTER I', +66460: 'UGARITIC LETTER U', +66461: 'UGARITIC LETTER SSU', +66463: 'UGARITIC WORD DIVIDER', +66464: 'OLD PERSIAN SIGN A', +66465: 'OLD PERSIAN SIGN I', +66466: 'OLD PERSIAN SIGN U', +66467: 'OLD PERSIAN SIGN KA', +66468: 'OLD PERSIAN SIGN KU', +66469: 'OLD PERSIAN SIGN GA', +66470: 'OLD PERSIAN SIGN GU', +66471: 'OLD PERSIAN SIGN XA', +66472: 'OLD PERSIAN SIGN CA', +66473: 'OLD PERSIAN SIGN JA', +66474: 'OLD PERSIAN SIGN JI', +66475: 'OLD PERSIAN SIGN TA', +66476: 'OLD PERSIAN SIGN TU', +66477: 'OLD PERSIAN SIGN DA', +66478: 'OLD PERSIAN SIGN DI', +66479: 'OLD PERSIAN SIGN DU', +66480: 'OLD PERSIAN SIGN THA', +66481: 'OLD PERSIAN SIGN PA', +66482: 'OLD PERSIAN SIGN BA', +66483: 'OLD PERSIAN SIGN FA', +66484: 'OLD PERSIAN SIGN NA', +66485: 'OLD PERSIAN SIGN NU', +66486: 'OLD PERSIAN SIGN MA', +66487: 'OLD PERSIAN SIGN MI', +66488: 'OLD PERSIAN SIGN MU', +66489: 'OLD PERSIAN SIGN YA', +66490: 'OLD PERSIAN SIGN VA', +66491: 'OLD PERSIAN SIGN VI', +66492: 'OLD PERSIAN SIGN RA', +66493: 'OLD PERSIAN SIGN RU', +66494: 'OLD PERSIAN SIGN LA', +66495: 'OLD PERSIAN SIGN SA', +66496: 'OLD PERSIAN SIGN ZA', +66497: 'OLD PERSIAN SIGN SHA', +66498: 'OLD PERSIAN SIGN SSA', +66499: 'OLD PERSIAN SIGN HA', +66504: 'OLD PERSIAN SIGN AURAMAZDAA', +66505: 'OLD PERSIAN SIGN AURAMAZDAA-2', +66506: 'OLD PERSIAN SIGN AURAMAZDAAHA', +66507: 'OLD PERSIAN SIGN XSHAAYATHIYA', +66508: 'OLD PERSIAN SIGN DAHYAAUSH', +66509: 'OLD PERSIAN SIGN DAHYAAUSH-2', +66510: 'OLD PERSIAN SIGN BAGA', +66511: 'OLD PERSIAN SIGN BUUMISH', +66512: 'OLD PERSIAN WORD DIVIDER', +66513: 'OLD PERSIAN NUMBER ONE', +66514: 'OLD PERSIAN NUMBER TWO', +66515: 'OLD PERSIAN NUMBER TEN', +66516: 'OLD PERSIAN NUMBER TWENTY', +66517: 'OLD PERSIAN NUMBER HUNDRED', 66560: 'DESERET CAPITAL LETTER LONG I', 66561: 'DESERET CAPITAL LETTER LONG E', 66562: 'DESERET CAPITAL LETTER LONG A', @@ -11661,6 +13526,8 @@ 66595: 'DESERET CAPITAL LETTER EM', 66596: 'DESERET CAPITAL LETTER EN', 66597: 'DESERET CAPITAL LETTER ENG', +66598: 'DESERET CAPITAL LETTER OI', +66599: 'DESERET CAPITAL LETTER EW', 66600: 'DESERET SMALL LETTER LONG I', 66601: 'DESERET SMALL LETTER LONG E', 66602: 'DESERET SMALL LETTER LONG A', @@ -11699,6 +13566,216 @@ 66635: 'DESERET SMALL LETTER EM', 66636: 'DESERET SMALL LETTER EN', 66637: 'DESERET SMALL LETTER ENG', +66638: 'DESERET SMALL LETTER OI', +66639: 'DESERET SMALL LETTER EW', +66640: 'SHAVIAN LETTER PEEP', +66641: 'SHAVIAN LETTER TOT', +66642: 'SHAVIAN LETTER KICK', +66643: 'SHAVIAN LETTER FEE', +66644: 'SHAVIAN LETTER THIGH', +66645: 'SHAVIAN LETTER SO', +66646: 'SHAVIAN LETTER SURE', +66647: 'SHAVIAN LETTER CHURCH', +66648: 'SHAVIAN LETTER YEA', +66649: 'SHAVIAN LETTER HUNG', +66650: 'SHAVIAN LETTER BIB', +66651: 'SHAVIAN LETTER DEAD', +66652: 'SHAVIAN LETTER GAG', +66653: 'SHAVIAN LETTER VOW', +66654: 'SHAVIAN LETTER THEY', +66655: 'SHAVIAN LETTER ZOO', +66656: 'SHAVIAN LETTER MEASURE', +66657: 'SHAVIAN LETTER JUDGE', +66658: 'SHAVIAN LETTER WOE', +66659: 'SHAVIAN LETTER HA-HA', +66660: 'SHAVIAN LETTER LOLL', +66661: 'SHAVIAN LETTER MIME', +66662: 'SHAVIAN LETTER IF', +66663: 'SHAVIAN LETTER EGG', +66664: 'SHAVIAN LETTER ASH', +66665: 'SHAVIAN LETTER ADO', +66666: 'SHAVIAN LETTER ON', +66667: 'SHAVIAN LETTER WOOL', +66668: 'SHAVIAN LETTER OUT', +66669: 'SHAVIAN LETTER AH', +66670: 'SHAVIAN LETTER ROAR', +66671: 'SHAVIAN LETTER NUN', +66672: 'SHAVIAN LETTER EAT', +66673: 'SHAVIAN LETTER AGE', +66674: 'SHAVIAN LETTER ICE', +66675: 'SHAVIAN LETTER UP', +66676: 'SHAVIAN LETTER OAK', +66677: 'SHAVIAN LETTER OOZE', +66678: 'SHAVIAN LETTER OIL', +66679: 'SHAVIAN LETTER AWE', +66680: 'SHAVIAN LETTER ARE', +66681: 'SHAVIAN LETTER OR', +66682: 'SHAVIAN LETTER AIR', +66683: 'SHAVIAN LETTER ERR', +66684: 'SHAVIAN LETTER ARRAY', +66685: 'SHAVIAN LETTER EAR', +66686: 'SHAVIAN LETTER IAN', +66687: 'SHAVIAN LETTER YEW', +66688: 'OSMANYA LETTER ALEF', +66689: 'OSMANYA LETTER BA', +66690: 'OSMANYA LETTER TA', +66691: 'OSMANYA LETTER JA', +66692: 'OSMANYA LETTER XA', +66693: 'OSMANYA LETTER KHA', +66694: 'OSMANYA LETTER DEEL', +66695: 'OSMANYA LETTER RA', +66696: 'OSMANYA LETTER SA', +66697: 'OSMANYA LETTER SHIIN', +66698: 'OSMANYA LETTER DHA', +66699: 'OSMANYA LETTER CAYN', +66700: 'OSMANYA LETTER GA', +66701: 'OSMANYA LETTER FA', +66702: 'OSMANYA LETTER QAAF', +66703: 'OSMANYA LETTER KAAF', +66704: 'OSMANYA LETTER LAAN', +66705: 'OSMANYA LETTER MIIN', +66706: 'OSMANYA LETTER NUUN', +66707: 'OSMANYA LETTER WAW', +66708: 'OSMANYA LETTER HA', +66709: 'OSMANYA LETTER YA', +66710: 'OSMANYA LETTER A', +66711: 'OSMANYA LETTER E', +66712: 'OSMANYA LETTER I', +66713: 'OSMANYA LETTER O', +66714: 'OSMANYA LETTER U', +66715: 'OSMANYA LETTER AA', +66716: 'OSMANYA LETTER EE', +66717: 'OSMANYA LETTER OO', +66720: 'OSMANYA DIGIT ZERO', +66721: 'OSMANYA DIGIT ONE', +66722: 'OSMANYA DIGIT TWO', +66723: 'OSMANYA DIGIT THREE', +66724: 'OSMANYA DIGIT FOUR', +66725: 'OSMANYA DIGIT FIVE', +66726: 'OSMANYA DIGIT SIX', +66727: 'OSMANYA DIGIT SEVEN', +66728: 'OSMANYA DIGIT EIGHT', +66729: 'OSMANYA DIGIT NINE', +67584: 'CYPRIOT SYLLABLE A', +67585: 'CYPRIOT SYLLABLE E', +67586: 'CYPRIOT SYLLABLE I', +67587: 'CYPRIOT SYLLABLE O', +67588: 'CYPRIOT SYLLABLE U', +67589: 'CYPRIOT SYLLABLE JA', +67592: 'CYPRIOT SYLLABLE JO', +67594: 'CYPRIOT SYLLABLE KA', +67595: 'CYPRIOT SYLLABLE KE', +67596: 'CYPRIOT SYLLABLE KI', +67597: 'CYPRIOT SYLLABLE KO', +67598: 'CYPRIOT SYLLABLE KU', +67599: 'CYPRIOT SYLLABLE LA', +67600: 'CYPRIOT SYLLABLE LE', +67601: 'CYPRIOT SYLLABLE LI', +67602: 'CYPRIOT SYLLABLE LO', +67603: 'CYPRIOT SYLLABLE LU', +67604: 'CYPRIOT SYLLABLE MA', +67605: 'CYPRIOT SYLLABLE ME', +67606: 'CYPRIOT SYLLABLE MI', +67607: 'CYPRIOT SYLLABLE MO', +67608: 'CYPRIOT SYLLABLE MU', +67609: 'CYPRIOT SYLLABLE NA', +67610: 'CYPRIOT SYLLABLE NE', +67611: 'CYPRIOT SYLLABLE NI', +67612: 'CYPRIOT SYLLABLE NO', +67613: 'CYPRIOT SYLLABLE NU', +67614: 'CYPRIOT SYLLABLE PA', +67615: 'CYPRIOT SYLLABLE PE', +67616: 'CYPRIOT SYLLABLE PI', +67617: 'CYPRIOT SYLLABLE PO', +67618: 'CYPRIOT SYLLABLE PU', +67619: 'CYPRIOT SYLLABLE RA', +67620: 'CYPRIOT SYLLABLE RE', +67621: 'CYPRIOT SYLLABLE RI', +67622: 'CYPRIOT SYLLABLE RO', +67623: 'CYPRIOT SYLLABLE RU', +67624: 'CYPRIOT SYLLABLE SA', +67625: 'CYPRIOT SYLLABLE SE', +67626: 'CYPRIOT SYLLABLE SI', +67627: 'CYPRIOT SYLLABLE SO', +67628: 'CYPRIOT SYLLABLE SU', +67629: 'CYPRIOT SYLLABLE TA', +67630: 'CYPRIOT SYLLABLE TE', +67631: 'CYPRIOT SYLLABLE TI', +67632: 'CYPRIOT SYLLABLE TO', +67633: 'CYPRIOT SYLLABLE TU', +67634: 'CYPRIOT SYLLABLE WA', +67635: 'CYPRIOT SYLLABLE WE', +67636: 'CYPRIOT SYLLABLE WI', +67637: 'CYPRIOT SYLLABLE WO', +67639: 'CYPRIOT SYLLABLE XA', +67640: 'CYPRIOT SYLLABLE XE', +67644: 'CYPRIOT SYLLABLE ZA', +67647: 'CYPRIOT SYLLABLE ZO', +68096: 'KHAROSHTHI LETTER A', +68097: 'KHAROSHTHI VOWEL SIGN I', +68098: 'KHAROSHTHI VOWEL SIGN U', +68099: 'KHAROSHTHI VOWEL SIGN VOCALIC R', +68101: 'KHAROSHTHI VOWEL SIGN E', +68102: 'KHAROSHTHI VOWEL SIGN O', +68108: 'KHAROSHTHI VOWEL LENGTH MARK', +68109: 'KHAROSHTHI SIGN DOUBLE RING BELOW', +68110: 'KHAROSHTHI SIGN ANUSVARA', +68111: 'KHAROSHTHI SIGN VISARGA', +68112: 'KHAROSHTHI LETTER KA', +68113: 'KHAROSHTHI LETTER KHA', +68114: 'KHAROSHTHI LETTER GA', +68115: 'KHAROSHTHI LETTER GHA', +68117: 'KHAROSHTHI LETTER CA', +68118: 'KHAROSHTHI LETTER CHA', +68119: 'KHAROSHTHI LETTER JA', +68121: 'KHAROSHTHI LETTER NYA', +68122: 'KHAROSHTHI LETTER TTA', +68123: 'KHAROSHTHI LETTER TTHA', +68124: 'KHAROSHTHI LETTER DDA', +68125: 'KHAROSHTHI LETTER DDHA', +68126: 'KHAROSHTHI LETTER NNA', +68127: 'KHAROSHTHI LETTER TA', +68128: 'KHAROSHTHI LETTER THA', +68129: 'KHAROSHTHI LETTER DA', +68130: 'KHAROSHTHI LETTER DHA', +68131: 'KHAROSHTHI LETTER NA', +68132: 'KHAROSHTHI LETTER PA', +68133: 'KHAROSHTHI LETTER PHA', +68134: 'KHAROSHTHI LETTER BA', +68135: 'KHAROSHTHI LETTER BHA', +68136: 'KHAROSHTHI LETTER MA', +68137: 'KHAROSHTHI LETTER YA', +68138: 'KHAROSHTHI LETTER RA', +68139: 'KHAROSHTHI LETTER LA', +68140: 'KHAROSHTHI LETTER VA', +68141: 'KHAROSHTHI LETTER SHA', +68142: 'KHAROSHTHI LETTER SSA', +68143: 'KHAROSHTHI LETTER SA', +68144: 'KHAROSHTHI LETTER ZA', +68145: 'KHAROSHTHI LETTER HA', +68146: 'KHAROSHTHI LETTER KKA', +68147: 'KHAROSHTHI LETTER TTTHA', +68152: 'KHAROSHTHI SIGN BAR ABOVE', +68153: 'KHAROSHTHI SIGN CAUDA', +68154: 'KHAROSHTHI SIGN DOT BELOW', +68159: 'KHAROSHTHI VIRAMA', +68160: 'KHAROSHTHI DIGIT ONE', +68161: 'KHAROSHTHI DIGIT TWO', +68162: 'KHAROSHTHI DIGIT THREE', +68163: 'KHAROSHTHI DIGIT FOUR', +68164: 'KHAROSHTHI NUMBER TEN', +68165: 'KHAROSHTHI NUMBER TWENTY', +68166: 'KHAROSHTHI NUMBER ONE HUNDRED', +68167: 'KHAROSHTHI NUMBER ONE THOUSAND', +68176: 'KHAROSHTHI PUNCTUATION DOT', +68177: 'KHAROSHTHI PUNCTUATION SMALL CIRCLE', +68178: 'KHAROSHTHI PUNCTUATION CIRCLE', +68179: 'KHAROSHTHI PUNCTUATION CRESCENT BAR', +68180: 'KHAROSHTHI PUNCTUATION MANGALAM', +68181: 'KHAROSHTHI PUNCTUATION LOTUS', +68182: 'KHAROSHTHI PUNCTUATION DANDA', +68183: 'KHAROSHTHI PUNCTUATION DOUBLE DANDA', +68184: 'KHAROSHTHI PUNCTUATION LINES', 118784: 'BYZANTINE MUSICAL SYMBOL PSILI', 118785: 'BYZANTINE MUSICAL SYMBOL DASEIA', 118786: 'BYZANTINE MUSICAL SYMBOL PERISPOMENI', @@ -12164,6 +14241,163 @@ 119259: 'MUSICAL SYMBOL SCANDICUS FLEXUS', 119260: 'MUSICAL SYMBOL TORCULUS RESUPINUS', 119261: 'MUSICAL SYMBOL PES SUBPUNCTIS', +119296: 'GREEK VOCAL NOTATION SYMBOL-1', +119297: 'GREEK VOCAL NOTATION SYMBOL-2', +119298: 'GREEK VOCAL NOTATION SYMBOL-3', +119299: 'GREEK VOCAL NOTATION SYMBOL-4', +119300: 'GREEK VOCAL NOTATION SYMBOL-5', +119301: 'GREEK VOCAL NOTATION SYMBOL-6', +119302: 'GREEK VOCAL NOTATION SYMBOL-7', +119303: 'GREEK VOCAL NOTATION SYMBOL-8', +119304: 'GREEK VOCAL NOTATION SYMBOL-9', +119305: 'GREEK VOCAL NOTATION SYMBOL-10', +119306: 'GREEK VOCAL NOTATION SYMBOL-11', +119307: 'GREEK VOCAL NOTATION SYMBOL-12', +119308: 'GREEK VOCAL NOTATION SYMBOL-13', +119309: 'GREEK VOCAL NOTATION SYMBOL-14', +119310: 'GREEK VOCAL NOTATION SYMBOL-15', +119311: 'GREEK VOCAL NOTATION SYMBOL-16', +119312: 'GREEK VOCAL NOTATION SYMBOL-17', +119313: 'GREEK VOCAL NOTATION SYMBOL-18', +119314: 'GREEK VOCAL NOTATION SYMBOL-19', +119315: 'GREEK VOCAL NOTATION SYMBOL-20', +119316: 'GREEK VOCAL NOTATION SYMBOL-21', +119317: 'GREEK VOCAL NOTATION SYMBOL-22', +119318: 'GREEK VOCAL NOTATION SYMBOL-23', +119319: 'GREEK VOCAL NOTATION SYMBOL-24', +119320: 'GREEK VOCAL NOTATION SYMBOL-50', +119321: 'GREEK VOCAL NOTATION SYMBOL-51', +119322: 'GREEK VOCAL NOTATION SYMBOL-52', +119323: 'GREEK VOCAL NOTATION SYMBOL-53', +119324: 'GREEK VOCAL NOTATION SYMBOL-54', +119325: 'GREEK INSTRUMENTAL NOTATION SYMBOL-1', +119326: 'GREEK INSTRUMENTAL NOTATION SYMBOL-2', +119327: 'GREEK INSTRUMENTAL NOTATION SYMBOL-4', +119328: 'GREEK INSTRUMENTAL NOTATION SYMBOL-5', +119329: 'GREEK INSTRUMENTAL NOTATION SYMBOL-7', +119330: 'GREEK INSTRUMENTAL NOTATION SYMBOL-8', +119331: 'GREEK INSTRUMENTAL NOTATION SYMBOL-11', +119332: 'GREEK INSTRUMENTAL NOTATION SYMBOL-12', +119333: 'GREEK INSTRUMENTAL NOTATION SYMBOL-13', +119334: 'GREEK INSTRUMENTAL NOTATION SYMBOL-14', +119335: 'GREEK INSTRUMENTAL NOTATION SYMBOL-17', +119336: 'GREEK INSTRUMENTAL NOTATION SYMBOL-18', +119337: 'GREEK INSTRUMENTAL NOTATION SYMBOL-19', +119338: 'GREEK INSTRUMENTAL NOTATION SYMBOL-23', +119339: 'GREEK INSTRUMENTAL NOTATION SYMBOL-24', +119340: 'GREEK INSTRUMENTAL NOTATION SYMBOL-25', +119341: 'GREEK INSTRUMENTAL NOTATION SYMBOL-26', +119342: 'GREEK INSTRUMENTAL NOTATION SYMBOL-27', +119343: 'GREEK INSTRUMENTAL NOTATION SYMBOL-29', +119344: 'GREEK INSTRUMENTAL NOTATION SYMBOL-30', +119345: 'GREEK INSTRUMENTAL NOTATION SYMBOL-32', +119346: 'GREEK INSTRUMENTAL NOTATION SYMBOL-36', +119347: 'GREEK INSTRUMENTAL NOTATION SYMBOL-37', +119348: 'GREEK INSTRUMENTAL NOTATION SYMBOL-38', +119349: 'GREEK INSTRUMENTAL NOTATION SYMBOL-39', +119350: 'GREEK INSTRUMENTAL NOTATION SYMBOL-40', +119351: 'GREEK INSTRUMENTAL NOTATION SYMBOL-42', +119352: 'GREEK INSTRUMENTAL NOTATION SYMBOL-43', +119353: 'GREEK INSTRUMENTAL NOTATION SYMBOL-45', +119354: 'GREEK INSTRUMENTAL NOTATION SYMBOL-47', +119355: 'GREEK INSTRUMENTAL NOTATION SYMBOL-48', +119356: 'GREEK INSTRUMENTAL NOTATION SYMBOL-49', +119357: 'GREEK INSTRUMENTAL NOTATION SYMBOL-50', +119358: 'GREEK INSTRUMENTAL NOTATION SYMBOL-51', +119359: 'GREEK INSTRUMENTAL NOTATION SYMBOL-52', +119360: 'GREEK INSTRUMENTAL NOTATION SYMBOL-53', +119361: 'GREEK INSTRUMENTAL NOTATION SYMBOL-54', +119362: 'COMBINING GREEK MUSICAL TRISEME', +119363: 'COMBINING GREEK MUSICAL TETRASEME', +119364: 'COMBINING GREEK MUSICAL PENTASEME', +119365: 'GREEK MUSICAL LEIMMA', +119552: 'MONOGRAM FOR EARTH', +119553: 'DIGRAM FOR HEAVENLY EARTH', +119554: 'DIGRAM FOR HUMAN EARTH', +119555: 'DIGRAM FOR EARTHLY HEAVEN', +119556: 'DIGRAM FOR EARTHLY HUMAN', +119557: 'DIGRAM FOR EARTH', +119558: 'TETRAGRAM FOR CENTRE', +119559: 'TETRAGRAM FOR FULL CIRCLE', +119560: 'TETRAGRAM FOR MIRED', +119561: 'TETRAGRAM FOR BARRIER', +119562: 'TETRAGRAM FOR KEEPING SMALL', +119563: 'TETRAGRAM FOR CONTRARIETY', +119564: 'TETRAGRAM FOR ASCENT', +119565: 'TETRAGRAM FOR OPPOSITION', +119566: 'TETRAGRAM FOR BRANCHING OUT', +119567: 'TETRAGRAM FOR DEFECTIVENESS OR DISTORTION', +119568: 'TETRAGRAM FOR DIVERGENCE', +119569: 'TETRAGRAM FOR YOUTHFULNESS', +119570: 'TETRAGRAM FOR INCREASE', +119571: 'TETRAGRAM FOR PENETRATION', +119572: 'TETRAGRAM FOR REACH', +119573: 'TETRAGRAM FOR CONTACT', +119574: 'TETRAGRAM FOR HOLDING BACK', +119575: 'TETRAGRAM FOR WAITING', +119576: 'TETRAGRAM FOR FOLLOWING', +119577: 'TETRAGRAM FOR ADVANCE', +119578: 'TETRAGRAM FOR RELEASE', +119579: 'TETRAGRAM FOR RESISTANCE', +119580: 'TETRAGRAM FOR EASE', +119581: 'TETRAGRAM FOR JOY', +119582: 'TETRAGRAM FOR CONTENTION', +119583: 'TETRAGRAM FOR ENDEAVOUR', +119584: 'TETRAGRAM FOR DUTIES', +119585: 'TETRAGRAM FOR CHANGE', +119586: 'TETRAGRAM FOR DECISIVENESS', +119587: 'TETRAGRAM FOR BOLD RESOLUTION', +119588: 'TETRAGRAM FOR PACKING', +119589: 'TETRAGRAM FOR LEGION', +119590: 'TETRAGRAM FOR CLOSENESS', +119591: 'TETRAGRAM FOR KINSHIP', +119592: 'TETRAGRAM FOR GATHERING', +119593: 'TETRAGRAM FOR STRENGTH', +119594: 'TETRAGRAM FOR PURITY', +119595: 'TETRAGRAM FOR FULLNESS', +119596: 'TETRAGRAM FOR RESIDENCE', +119597: 'TETRAGRAM FOR LAW OR MODEL', +119598: 'TETRAGRAM FOR RESPONSE', +119599: 'TETRAGRAM FOR GOING TO MEET', +119600: 'TETRAGRAM FOR ENCOUNTERS', +119601: 'TETRAGRAM FOR STOVE', +119602: 'TETRAGRAM FOR GREATNESS', +119603: 'TETRAGRAM FOR ENLARGEMENT', +119604: 'TETRAGRAM FOR PATTERN', +119605: 'TETRAGRAM FOR RITUAL', +119606: 'TETRAGRAM FOR FLIGHT', +119607: 'TETRAGRAM FOR VASTNESS OR WASTING', +119608: 'TETRAGRAM FOR CONSTANCY', +119609: 'TETRAGRAM FOR MEASURE', +119610: 'TETRAGRAM FOR ETERNITY', +119611: 'TETRAGRAM FOR UNITY', +119612: 'TETRAGRAM FOR DIMINISHMENT', +119613: 'TETRAGRAM FOR CLOSED MOUTH', +119614: 'TETRAGRAM FOR GUARDEDNESS', +119615: 'TETRAGRAM FOR GATHERING IN', +119616: 'TETRAGRAM FOR MASSING', +119617: 'TETRAGRAM FOR ACCUMULATION', +119618: 'TETRAGRAM FOR EMBELLISHMENT', +119619: 'TETRAGRAM FOR DOUBT', +119620: 'TETRAGRAM FOR WATCH', +119621: 'TETRAGRAM FOR SINKING', +119622: 'TETRAGRAM FOR INNER', +119623: 'TETRAGRAM FOR DEPARTURE', +119624: 'TETRAGRAM FOR DARKENING', +119625: 'TETRAGRAM FOR DIMMING', +119626: 'TETRAGRAM FOR EXHAUSTION', +119627: 'TETRAGRAM FOR SEVERANCE', +119628: 'TETRAGRAM FOR STOPPAGE', +119629: 'TETRAGRAM FOR HARDNESS', +119630: 'TETRAGRAM FOR COMPLETION', +119631: 'TETRAGRAM FOR CLOSURE', +119632: 'TETRAGRAM FOR FAILURE', +119633: 'TETRAGRAM FOR AGGRAVATION', +119634: 'TETRAGRAM FOR COMPLIANCE', +119635: 'TETRAGRAM FOR ON THE VERGE', +119636: 'TETRAGRAM FOR DIFFICULTIES', +119637: 'TETRAGRAM FOR LABOURING', +119638: 'TETRAGRAM FOR FOSTERING', 119808: 'MATHEMATICAL BOLD CAPITAL A', 119809: 'MATHEMATICAL BOLD CAPITAL B', 119810: 'MATHEMATICAL BOLD CAPITAL C', @@ -12346,6 +14580,7 @@ 119998: 'MATHEMATICAL SCRIPT SMALL I', 119999: 'MATHEMATICAL SCRIPT SMALL J', 120000: 'MATHEMATICAL SCRIPT SMALL K', +120001: 'MATHEMATICAL SCRIPT SMALL L', 120002: 'MATHEMATICAL SCRIPT SMALL M', 120003: 'MATHEMATICAL SCRIPT SMALL N', 120005: 'MATHEMATICAL SCRIPT SMALL P', @@ -12815,6 +15050,8 @@ 120481: 'MATHEMATICAL MONOSPACE SMALL X', 120482: 'MATHEMATICAL MONOSPACE SMALL Y', 120483: 'MATHEMATICAL MONOSPACE SMALL Z', +120484: 'MATHEMATICAL ITALIC SMALL DOTLESS I', +120485: 'MATHEMATICAL ITALIC SMALL DOTLESS J', 120488: 'MATHEMATICAL BOLD CAPITAL ALPHA', 120489: 'MATHEMATICAL BOLD CAPITAL BETA', 120490: 'MATHEMATICAL BOLD CAPITAL GAMMA', @@ -13794,6 +16031,246 @@ 917629: 'TAG RIGHT CURLY BRACKET', 917630: 'TAG TILDE', 917631: 'CANCEL TAG', +917760: 'VARIATION SELECTOR-17', +917761: 'VARIATION SELECTOR-18', +917762: 'VARIATION SELECTOR-19', +917763: 'VARIATION SELECTOR-20', +917764: 'VARIATION SELECTOR-21', +917765: 'VARIATION SELECTOR-22', +917766: 'VARIATION SELECTOR-23', +917767: 'VARIATION SELECTOR-24', +917768: 'VARIATION SELECTOR-25', +917769: 'VARIATION SELECTOR-26', +917770: 'VARIATION SELECTOR-27', +917771: 'VARIATION SELECTOR-28', +917772: 'VARIATION SELECTOR-29', +917773: 'VARIATION SELECTOR-30', +917774: 'VARIATION SELECTOR-31', +917775: 'VARIATION SELECTOR-32', +917776: 'VARIATION SELECTOR-33', +917777: 'VARIATION SELECTOR-34', +917778: 'VARIATION SELECTOR-35', +917779: 'VARIATION SELECTOR-36', +917780: 'VARIATION SELECTOR-37', +917781: 'VARIATION SELECTOR-38', +917782: 'VARIATION SELECTOR-39', +917783: 'VARIATION SELECTOR-40', +917784: 'VARIATION SELECTOR-41', +917785: 'VARIATION SELECTOR-42', +917786: 'VARIATION SELECTOR-43', +917787: 'VARIATION SELECTOR-44', +917788: 'VARIATION SELECTOR-45', +917789: 'VARIATION SELECTOR-46', +917790: 'VARIATION SELECTOR-47', +917791: 'VARIATION SELECTOR-48', +917792: 'VARIATION SELECTOR-49', +917793: 'VARIATION SELECTOR-50', +917794: 'VARIATION SELECTOR-51', +917795: 'VARIATION SELECTOR-52', +917796: 'VARIATION SELECTOR-53', +917797: 'VARIATION SELECTOR-54', +917798: 'VARIATION SELECTOR-55', +917799: 'VARIATION SELECTOR-56', +917800: 'VARIATION SELECTOR-57', +917801: 'VARIATION SELECTOR-58', +917802: 'VARIATION SELECTOR-59', +917803: 'VARIATION SELECTOR-60', +917804: 'VARIATION SELECTOR-61', +917805: 'VARIATION SELECTOR-62', +917806: 'VARIATION SELECTOR-63', +917807: 'VARIATION SELECTOR-64', +917808: 'VARIATION SELECTOR-65', +917809: 'VARIATION SELECTOR-66', +917810: 'VARIATION SELECTOR-67', +917811: 'VARIATION SELECTOR-68', +917812: 'VARIATION SELECTOR-69', +917813: 'VARIATION SELECTOR-70', +917814: 'VARIATION SELECTOR-71', +917815: 'VARIATION SELECTOR-72', +917816: 'VARIATION SELECTOR-73', +917817: 'VARIATION SELECTOR-74', +917818: 'VARIATION SELECTOR-75', +917819: 'VARIATION SELECTOR-76', +917820: 'VARIATION SELECTOR-77', +917821: 'VARIATION SELECTOR-78', +917822: 'VARIATION SELECTOR-79', +917823: 'VARIATION SELECTOR-80', +917824: 'VARIATION SELECTOR-81', +917825: 'VARIATION SELECTOR-82', +917826: 'VARIATION SELECTOR-83', +917827: 'VARIATION SELECTOR-84', +917828: 'VARIATION SELECTOR-85', +917829: 'VARIATION SELECTOR-86', +917830: 'VARIATION SELECTOR-87', +917831: 'VARIATION SELECTOR-88', +917832: 'VARIATION SELECTOR-89', +917833: 'VARIATION SELECTOR-90', +917834: 'VARIATION SELECTOR-91', +917835: 'VARIATION SELECTOR-92', +917836: 'VARIATION SELECTOR-93', +917837: 'VARIATION SELECTOR-94', +917838: 'VARIATION SELECTOR-95', +917839: 'VARIATION SELECTOR-96', +917840: 'VARIATION SELECTOR-97', +917841: 'VARIATION SELECTOR-98', +917842: 'VARIATION SELECTOR-99', +917843: 'VARIATION SELECTOR-100', +917844: 'VARIATION SELECTOR-101', +917845: 'VARIATION SELECTOR-102', +917846: 'VARIATION SELECTOR-103', +917847: 'VARIATION SELECTOR-104', +917848: 'VARIATION SELECTOR-105', +917849: 'VARIATION SELECTOR-106', +917850: 'VARIATION SELECTOR-107', +917851: 'VARIATION SELECTOR-108', +917852: 'VARIATION SELECTOR-109', +917853: 'VARIATION SELECTOR-110', +917854: 'VARIATION SELECTOR-111', +917855: 'VARIATION SELECTOR-112', +917856: 'VARIATION SELECTOR-113', +917857: 'VARIATION SELECTOR-114', +917858: 'VARIATION SELECTOR-115', +917859: 'VARIATION SELECTOR-116', +917860: 'VARIATION SELECTOR-117', +917861: 'VARIATION SELECTOR-118', +917862: 'VARIATION SELECTOR-119', +917863: 'VARIATION SELECTOR-120', +917864: 'VARIATION SELECTOR-121', +917865: 'VARIATION SELECTOR-122', +917866: 'VARIATION SELECTOR-123', +917867: 'VARIATION SELECTOR-124', +917868: 'VARIATION SELECTOR-125', +917869: 'VARIATION SELECTOR-126', +917870: 'VARIATION SELECTOR-127', +917871: 'VARIATION SELECTOR-128', +917872: 'VARIATION SELECTOR-129', +917873: 'VARIATION SELECTOR-130', +917874: 'VARIATION SELECTOR-131', +917875: 'VARIATION SELECTOR-132', +917876: 'VARIATION SELECTOR-133', +917877: 'VARIATION SELECTOR-134', +917878: 'VARIATION SELECTOR-135', +917879: 'VARIATION SELECTOR-136', +917880: 'VARIATION SELECTOR-137', +917881: 'VARIATION SELECTOR-138', +917882: 'VARIATION SELECTOR-139', +917883: 'VARIATION SELECTOR-140', +917884: 'VARIATION SELECTOR-141', +917885: 'VARIATION SELECTOR-142', +917886: 'VARIATION SELECTOR-143', +917887: 'VARIATION SELECTOR-144', +917888: 'VARIATION SELECTOR-145', +917889: 'VARIATION SELECTOR-146', +917890: 'VARIATION SELECTOR-147', +917891: 'VARIATION SELECTOR-148', +917892: 'VARIATION SELECTOR-149', +917893: 'VARIATION SELECTOR-150', +917894: 'VARIATION SELECTOR-151', +917895: 'VARIATION SELECTOR-152', +917896: 'VARIATION SELECTOR-153', +917897: 'VARIATION SELECTOR-154', +917898: 'VARIATION SELECTOR-155', +917899: 'VARIATION SELECTOR-156', +917900: 'VARIATION SELECTOR-157', +917901: 'VARIATION SELECTOR-158', +917902: 'VARIATION SELECTOR-159', +917903: 'VARIATION SELECTOR-160', +917904: 'VARIATION SELECTOR-161', +917905: 'VARIATION SELECTOR-162', +917906: 'VARIATION SELECTOR-163', +917907: 'VARIATION SELECTOR-164', +917908: 'VARIATION SELECTOR-165', +917909: 'VARIATION SELECTOR-166', +917910: 'VARIATION SELECTOR-167', +917911: 'VARIATION SELECTOR-168', +917912: 'VARIATION SELECTOR-169', +917913: 'VARIATION SELECTOR-170', +917914: 'VARIATION SELECTOR-171', +917915: 'VARIATION SELECTOR-172', +917916: 'VARIATION SELECTOR-173', +917917: 'VARIATION SELECTOR-174', +917918: 'VARIATION SELECTOR-175', +917919: 'VARIATION SELECTOR-176', +917920: 'VARIATION SELECTOR-177', +917921: 'VARIATION SELECTOR-178', +917922: 'VARIATION SELECTOR-179', +917923: 'VARIATION SELECTOR-180', +917924: 'VARIATION SELECTOR-181', +917925: 'VARIATION SELECTOR-182', +917926: 'VARIATION SELECTOR-183', +917927: 'VARIATION SELECTOR-184', +917928: 'VARIATION SELECTOR-185', +917929: 'VARIATION SELECTOR-186', +917930: 'VARIATION SELECTOR-187', +917931: 'VARIATION SELECTOR-188', +917932: 'VARIATION SELECTOR-189', +917933: 'VARIATION SELECTOR-190', +917934: 'VARIATION SELECTOR-191', +917935: 'VARIATION SELECTOR-192', +917936: 'VARIATION SELECTOR-193', +917937: 'VARIATION SELECTOR-194', +917938: 'VARIATION SELECTOR-195', +917939: 'VARIATION SELECTOR-196', +917940: 'VARIATION SELECTOR-197', +917941: 'VARIATION SELECTOR-198', +917942: 'VARIATION SELECTOR-199', +917943: 'VARIATION SELECTOR-200', +917944: 'VARIATION SELECTOR-201', +917945: 'VARIATION SELECTOR-202', +917946: 'VARIATION SELECTOR-203', +917947: 'VARIATION SELECTOR-204', +917948: 'VARIATION SELECTOR-205', +917949: 'VARIATION SELECTOR-206', +917950: 'VARIATION SELECTOR-207', +917951: 'VARIATION SELECTOR-208', +917952: 'VARIATION SELECTOR-209', +917953: 'VARIATION SELECTOR-210', +917954: 'VARIATION SELECTOR-211', +917955: 'VARIATION SELECTOR-212', +917956: 'VARIATION SELECTOR-213', +917957: 'VARIATION SELECTOR-214', +917958: 'VARIATION SELECTOR-215', +917959: 'VARIATION SELECTOR-216', +917960: 'VARIATION SELECTOR-217', +917961: 'VARIATION SELECTOR-218', +917962: 'VARIATION SELECTOR-219', +917963: 'VARIATION SELECTOR-220', +917964: 'VARIATION SELECTOR-221', +917965: 'VARIATION SELECTOR-222', +917966: 'VARIATION SELECTOR-223', +917967: 'VARIATION SELECTOR-224', +917968: 'VARIATION SELECTOR-225', +917969: 'VARIATION SELECTOR-226', +917970: 'VARIATION SELECTOR-227', +917971: 'VARIATION SELECTOR-228', +917972: 'VARIATION SELECTOR-229', +917973: 'VARIATION SELECTOR-230', +917974: 'VARIATION SELECTOR-231', +917975: 'VARIATION SELECTOR-232', +917976: 'VARIATION SELECTOR-233', +917977: 'VARIATION SELECTOR-234', +917978: 'VARIATION SELECTOR-235', +917979: 'VARIATION SELECTOR-236', +917980: 'VARIATION SELECTOR-237', +917981: 'VARIATION SELECTOR-238', +917982: 'VARIATION SELECTOR-239', +917983: 'VARIATION SELECTOR-240', +917984: 'VARIATION SELECTOR-241', +917985: 'VARIATION SELECTOR-242', +917986: 'VARIATION SELECTOR-243', +917987: 'VARIATION SELECTOR-244', +917988: 'VARIATION SELECTOR-245', +917989: 'VARIATION SELECTOR-246', +917990: 'VARIATION SELECTOR-247', +917991: 'VARIATION SELECTOR-248', +917992: 'VARIATION SELECTOR-249', +917993: 'VARIATION SELECTOR-250', +917994: 'VARIATION SELECTOR-251', +917995: 'VARIATION SELECTOR-252', +917996: 'VARIATION SELECTOR-253', +917997: 'VARIATION SELECTOR-254', +917998: 'VARIATION SELECTOR-255', +917999: 'VARIATION SELECTOR-256', } _code_by_name = dict(map(lambda x:(x[1],x[0]), _charnames.iteritems())) @@ -13850,7 +16327,7 @@ raise KeyError code = int(cjk_code, 16) if (0x3400 <= code <= 0x4DB5 or - 0x4E00 <= code <= 0x9FA5 or + 0x4E00 <= code <= 0x9FBB or 0x20000 <= code <= 0x2A6D6): return code raise KeyError @@ -13864,7 +16341,7 @@ def name(code): if (0x3400 <= code <= 0x4DB5 or - 0x4E00 <= code <= 0x9FA5 or + 0x4E00 <= code <= 0x9FBB or 0x20000 <= code <= 0x2A6D6): return "CJK UNIFIED IDEOGRAPH-" + hex(code)[2:].upper() if 0xAC00 <= code <= 0xD7A3: @@ -13885,15 +16362,18 @@ ('Cc', 'S', 'N', 1, 0), ('Cc', 'WS', 'N', 1, 0), ('Cf', 'AL', 'N', 0, 0), +('Cf', 'BN', 'A', 0, 0), ('Cf', 'BN', 'N', 0, 0), ('Cf', 'L', 'N', 0, 0), ('Cf', 'LRE', 'N', 0, 0), ('Cf', 'LRO', 'N', 0, 0), +('Cf', 'ON', 'N', 0, 0), ('Cf', 'PDF', 'N', 0, 0), ('Cf', 'R', 'N', 0, 0), ('Cf', 'RLE', 'N', 0, 0), ('Cf', 'RLO', 'N', 0, 0), ('Cn', '', 'N', 0, 0), +('Cn', '', 'W', 0, 0), ('Co', 'L', 'A', 0, 0), ('Cs', 'L', 'N', 0, 0), ('Ll', 'L', 'A', 34, 0), @@ -13905,6 +16385,8 @@ ('Lm', 'L', 'H', 2, 0), ('Lm', 'L', 'N', 2, 0), ('Lm', 'L', 'W', 2, 0), +('Lm', 'ON', 'A', 2, 0), +('Lm', 'ON', 'N', 2, 0), ('Lo', 'AL', 'N', 2, 0), ('Lo', 'L', 'H', 2, 0), ('Lo', 'L', 'N', 2, 0), @@ -13918,7 +16400,9 @@ ('Mc', 'L', 'N', 0, 0), ('Mc', 'L', 'N', 0, 216), ('Mc', 'L', 'N', 0, 226), +('Mc', 'NSM', 'N', 0, 0), ('Me', 'NSM', 'N', 0, 0), +('Mn', 'L', 'N', 0, 0), ('Mn', 'NSM', 'A', 0, 0), ('Mn', 'NSM', 'A', 0, 1), ('Mn', 'NSM', 'A', 0, 202), @@ -13989,27 +16473,28 @@ ('Nl', 'L', 'N', 0, 0), ('Nl', 'L', 'N', 64, 0), ('Nl', 'L', 'W', 64, 0), +('Nl', 'ON', 'N', 64, 0), ('No', 'EN', 'A', 64, 0), ('No', 'EN', 'A', 192, 0), -('No', 'EN', 'A', 448, 0), ('No', 'EN', 'N', 192, 0), -('No', 'EN', 'N', 448, 0), ('No', 'L', 'N', 0, 0), ('No', 'L', 'N', 64, 0), +('No', 'L', 'N', 192, 0), ('No', 'L', 'W', 64, 0), ('No', 'ON', 'A', 64, 0), ('No', 'ON', 'A', 192, 0), ('No', 'ON', 'N', 64, 0), ('No', 'ON', 'N', 192, 0), ('No', 'ON', 'W', 64, 0), +('No', 'R', 'N', 64, 0), +('No', 'R', 'N', 192, 0), ('Pc', 'ON', 'F', 0, 0), -('Pc', 'ON', 'H', 0, 0), ('Pc', 'ON', 'N', 0, 0), ('Pc', 'ON', 'Na', 0, 0), ('Pc', 'ON', 'W', 0, 0), -('Pd', 'ET', 'F', 0, 0), -('Pd', 'ET', 'Na', 0, 0), -('Pd', 'ET', 'W', 0, 0), +('Pd', 'ES', 'F', 0, 0), +('Pd', 'ES', 'Na', 0, 0), +('Pd', 'ES', 'W', 0, 0), ('Pd', 'ON', 'A', 0, 0), ('Pd', 'ON', 'N', 0, 0), ('Pd', 'ON', 'W', 0, 0), @@ -14031,8 +16516,6 @@ ('Po', 'CS', 'N', 0, 0), ('Po', 'CS', 'Na', 0, 0), ('Po', 'CS', 'W', 0, 0), -('Po', 'ES', 'F', 0, 0), -('Po', 'ES', 'Na', 0, 0), ('Po', 'ET', 'A', 0, 0), ('Po', 'ET', 'F', 0, 0), ('Po', 'ET', 'N', 0, 0), @@ -14065,11 +16548,13 @@ ('Sk', 'ON', 'N', 0, 0), ('Sk', 'ON', 'Na', 0, 0), ('Sk', 'ON', 'W', 0, 0), +('Sm', 'CS', 'N', 0, 0), +('Sm', 'ES', 'F', 0, 0), +('Sm', 'ES', 'N', 0, 0), +('Sm', 'ES', 'Na', 0, 0), +('Sm', 'ES', 'W', 0, 0), ('Sm', 'ET', 'A', 0, 0), -('Sm', 'ET', 'F', 0, 0), ('Sm', 'ET', 'N', 0, 0), -('Sm', 'ET', 'Na', 0, 0), -('Sm', 'ET', 'W', 0, 0), ('Sm', 'L', 'N', 0, 0), ('Sm', 'ON', 'A', 0, 0), ('Sm', 'ON', 'A', 512, 0), @@ -14095,29 +16580,28 @@ ('So', 'ON', 'W', 0, 0), ('Zl', 'WS', 'N', 5, 0), ('Zp', 'B', 'N', 5, 0), -('Zs', 'BN', 'N', 1, 0), ('Zs', 'CS', 'N', 1, 0), ('Zs', 'WS', 'F', 1, 0), ('Zs', 'WS', 'N', 1, 0), ('Zs', 'WS', 'Na', 1, 0), ] _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,,,,,,,,,,,,,,,,,,,,' -',,,,,,,,,,,,,,,,,,,,,,,0111111112222222222222222222222222,345678' -'\x08\x08\x089:\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08' -'\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08' -'\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08' -'\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08;<\x08\x08=>?@\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08' -',,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,' -',,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,' -',,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,A\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08' -'\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08,,B\x08\x08\x08\x08\x08' -'\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08' -'\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08' +'\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\x19\x1a\x08\x08\x1b\x1c\x1d\x1e\x1f !"#$%&\'()*+,-./01222222222222' +'2222222222222322222222222222222222222222222222222222222222222222' +'2222222222222222222222222222222452226\x08\x0878\x08\x08\x0822222222222222222222' +'222222222222222222222229::::::::;;;;;;;;;;;;;;;;;;;;;;;;;2<=>?@A' +'BC\x08DE\x08\x08\x08F\x08G\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08' '\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08' '\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08' +'\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08HIJKLMNO\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08' +'2222222222222222222222222222222222222222222222222222222222222222' +'2222222222222222222222222222222222222222222222222222222222222222' +'22222222222222222222222222222222222222PQQQQQQQQQQQQQQQQQQQQQQQQQ' +'QQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQ22RQQQQS' +'QQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQ' +'QQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQ' +'QQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQ' +'QQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQS' '\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08' '\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08' '\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08' @@ -14158,296 +16642,368 @@ '\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08' '\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08' '\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08' -'C\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08' +'TU\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08' '\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08' '\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08' '\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08\x08' -'2222222222222222222222222222222222222222222222222222222222222222' -'2222222222222222222222222222222222222222222222222222222222222222' -'2222222222222222222222222222222222222222222222222222222222222222' -'222222222222222222222222222222222222222222222222222222222222222D' -'2222222222222222222222222222222222222222222222222222222222222222' -'2222222222222222222222222222222222222222222222222222222222222222' -'2222222222222222222222222222222222222222222222222222222222222222' -'222222222222222222222222222222222222222222222222222222222222222D' +';;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;' +';;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;' +';;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;' +';;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;V' +';;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;' +';;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;' +';;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;' +';;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;V' ) _db_pages = ( -'\x01\x01\x01\x01\x01\x01\x01\x01\x01\x02\x00\x02\x03\x00\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x00\x00\x00\x02\xdb\xa3\xa3\x9c\xb2\x9c\xa3\xa3\xaa\x89\xa3\xbc\x95\x80\x95\x98gggggggggg\x95\xa3\xc7\xc6\xc7\xa3' -'\xa3""""""""""""""""""""""""""\xaa\xa3\x89\xb7}\xb7\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\xaa\xc6\x89\xc6\x01' -'\x01\x01\x01\x01\x01\x00\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\xd8\x9f\xb2\xb2\xae\xb2\xd3\xcf\xb4\xd2\x10\x90\xc6\x82\xcf\xb7\xca\xb9oo\xb4\x12\xcf\x9f\xb4o\x10\x8duuu\x9f' -'!!!!!!\x1f!!!!!!!!!\x1f!!!!!!\xbf\x1f!!!!!\x1f\x10\x10\x10\x12\x12\x12\x12\x10\x12\x10\x10\x10\x12\x10\x10\x12\x12\x10\x12\x10\x10\x12\x12\x12\xbf\x10\x10\x10\x12\x10\x12\x10\x12' -'!\x10!\x12!\x12!\x12!\x12!\x12!\x12!\x12!\x10!\x10!\x12!\x12!\x12!\x10!\x12!\x12!\x12!\x12!\x12\x1f\x10!\x12!\x10!\x12!\x12!\x10\x1f\x10!\x12!\x12\x10!\x12!\x12!\x12\x1f' -'\x10\x1f\x10!\x10!\x12!\x10\x10\x1f\x10!\x10!\x12!\x12\x1f\x10!\x12!\x12!\x12!\x12!\x12!\x12!\x12!\x12!\x12\x1f\x10!\x12!\x10!\x12!\x12!\x12!\x12!\x12!\x12!!\x12!\x12!\x12\x12' -'\x12!!\x12!\x12!!\x12!!!\x12\x12!!!!\x12!!\x12!!!\x12\x12\x12!!\x12!!\x12!\x12!\x12!!\x12!\x12\x12!\x12!!\x12!!!\x12!\x12!!\x12\x12\x1b!\x12\x12\x12' -'\x1b\x1b\x1b\x1b!\x1e\x12!\x1e\x12!\x1e\x12!\x10!\x10!\x10!\x10!\x10!\x10!\x10!\x10\x12!\x12!\x12!\x12!\x12!\x12!\x12!\x12!\x12!\x12\x12!\x1e\x12!\x12!!!\x12!\x12!\x12!\x12' -'!\x12!\x12!\x12!\x12!\x12!\x12!\x12!\x12!\x12!\x12!\x12!\x12!\x12!\x12!\x12!\x12!\r!\x12!\x12!\x12!\x12!\x12!\x12!\x12!\x12!\x12\r\r\r\r\r\r\r\r\r\r\r\r' -'\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\x12\x10\x12\x12\x12\x12\x12\x12\x12\x12\x12\x12\x12\x12\x12\x12\x12\x10\x12\x12\x12\x12\x12\x12\x12\x12\x12\x12\x12\x12\x12\x12\x12\x12\x12\x12\x12\x12\x12\x12\x12\x12\x12\x12\x12\x12\x12\x12' -'\x12\x12\x12\x12\x12\x12\x12\x12\x12\x12\x12\x12\x12\x12\x12\x12\x12\x12\x12\x12\x12\x12\x12\x12\x12\x12\x12\x12\x12\x12\x12\x12\x12\x12\x12\x12\x12\x12\x12\x12\x12\x12\x12\x12\x12\x12\r\r\x17\x17\x17\x17\x17\x17\x17\x17\x17\xb6\xb6\x17\x17\x17\x17\x17' -'\x17\x17\xb6\xb6\xb4\xb6\xb6\xb4\xb6\xb4\xb4\xb4\xb6\xb4\xb6\xb6\x15\x17\xb6\xb6\xb6\xb6\xb6\xb6\xb4\xb4\xb4\xb4\xb6\xb4\xb6\xb4\x17\x17\x17\x17\x17\xb6\xb6\xb6\xb6\xb6\xb6\xb6\xb6\xb6\x17\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r' -',,,,,,,,,,,,,,,,,,,,,-++++-*+++++))++++))+++++++++++(((((++++,,,' -",,,,,0,+++,,,++'\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r//.,,,,,,,,,,,,,\r\r\r\r\xb6\xb6\r\r\r\r\x17\r\r\r\xa2\r" -'\r\r\r\r\xb6\xb6!\xa2!!!\r!\r!!\x12\x1f\x1f\x1f\x1f\x1f\x1f\x1f\x1f\x1f\x1f\x1f\x1f\x1f\x1f\x1f\x1f\x1f\r\x1f\x1f\x1f\x1f\x1f\x1f\x1f!!\x12\x12\x12\x12\x12\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10' -'\x10\x10\x12\x10\x10\x10\x10\x10\x10\x10\x12\x12\x12\x12\x12\r\x12\x12!!!\x12\x12\x12!\x12!\x12!\x12!\x12!\x12!\x12!\x12!\x12!\x12!\x12!\x12!\x12\x12\x12\x12\x12!\x12\xc4\r\r\r\r\r\r\r\r\r' -'!\x1f!!!!!!!!!!!!!!\x1f\x1f\x1f\x1f\x1f\x1f\x1f\x1f\x1f\x1f\x1f\x1f\x1f\x1f\x1f\x1f\x1f\x1f\x1f\x1f\x1f\x1f\x1f\x1f\x1f\x1f\x1f\x1f\x1f\x1f\x1f\x1f\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\x12\x10\x12\x12\x12\x12\x12\x12\x12\x12\x12\x12\x12\x12\x12\x12!\x12!\x12!\x12!\x12!\x12!\x12!\x12!\x12!\x12!\x12!\x12!\x12!\x12!\x12!\x12!\x12' -'!\x12\xcd]]]]\r&&!\x12!\x12!\x12!\x12!\x12!\x12!\x12!\x12!\x12!\x12!\x12!\x12!\x12!\x12!\x12!\x12!\x12!\x12!\x12!\x12!\x12!\x12!\x12!\x12!\x12!\x12!\x12' -'!!\x12!\x12!\x12!\x12!\x12!\x12!\x12\r!\x12!\x12!\x12!\x12!\x12!\x12!\x12!\x12!\x12!\x12!\x12!\x12!\x12!\x12!\x12!\x12!\x12!\x12!\x12\r\r!\x12\r\r\r\r\r\r' -'!\x12!\x12!\x12!\x12!\x12!\x12!\x12!\x12\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r!!!!!!!!!!!!!!!' -'!!!!!!!!!!!!!!!!!!!!!!!\r\r\x17\x9e\x9e\x9e\x9e\x9e\x9e\r\x12\x12\x12\x12\x12\x12\x12\x12\x12\x12\x12\x12\x12\x12\x12\x12\x12\x12\x12\x12\x12\x12\x12\x12\x12\x12\x12\x12\x12\x12\x12' -'\x12\x12\x12\x12\x12\x12\x12\x12\r\x9e\x83\r\r\r\r\r\rZ]]]]Z]]][Z]]]]]]\rZZZZZ]]Z]][\\]56789:;<=>\r?@A\xa5B' -'\xa5CD\xa5]\r\r\r\r\r\r\r\r\r\r\r\x1d\x1d\x1d\x1d\x1d\x1d\x1d\x1d\x1d\x1d\x1d\x1d\x1d\x1d\x1d\x1d\x1d\x1d\x1d\x1d\x1d\x1d\x1d\x1d\x1d\x1d\x1d\r\r\r\r\r\x1d\x1d\x1d\xa5\xa5\r\r\r\r\r\r\r\r\r\r\r' -'\r\r\r\r\r\r\r\r\r\r\r\r\x94\r\r\r\r\r\r\r\r\r\r\r\r\r\r\x91\r\r\r\x91\r\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\r\r\r\r\r' -'\x14\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19FGHIJKLM]]Z\r\r\r\r\r\r\r\r\r\rdddddddddd\x9b\x92\x92\x91\x19\x19N\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19' -'\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19' -'\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x91\x19]]]]]]]\x04&]]]]Z]\x14\x14]]\xd2Z]]Z\r\rffffffffff\x19\x19\x19\xc9\xc9\r' -'\x91\x91\x91\x91\x91\x91\x91\x91\x91\x91\x91\x91\x91\x91\r\x05\x19O\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\r\r\r]Z]]Z]]ZZZ]ZZ]Z]' -']]Z]Z]Z]Z]]\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r' -'\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x1911111111111\x19\r\r\r\r\r\r\r\r\r\r\r\r\r\r' -'\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r' -'\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r' -'\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r' -'\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r' -'\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r' -'\r11#\r\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\r\r3\x1b##' -'#11111111####4\r\r\x1b]Z]]\r\r\r\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b11\x9e\x9ehhhhhhhhhh\x9e\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r' -'\r1##\r\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\r\r\x1b\x1b\r\r\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\r\x1b\x1b\x1b\x1b\x1b\x1b\x1b\r\x1b\r\r\r\x1b\x1b\x1b\x1b\r\r3\r##' -'#1111\r\r##\r\r##4\r\r\r\r\r\r\r\r\r#\r\r\r\r\x1b\x1b\r\x1b\x1b\x1b11\r\rhhhhhhhhhh\x1b\x1b\xb1\xb1ssssrs\xcd\r\r\r\r\r' -'\r\r1\r\r\x1b\x1b\x1b\x1b\x1b\x1b\r\r\r\r\x1b\x1b\r\r\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\r\x1b\x1b\x1b\x1b\x1b\x1b\x1b\r\x1b\x1b\r\x1b\x1b\r\x1b\x1b\r\r3\r##' -'#11\r\r\r\r11\r\r114\r\r\r\r\r\r\r\r\r\r\r\x1b\x1b\x1b\x1b\r\x1b\r\r\r\r\r\r\rhhhhhhhhhh11\x1b\x1b\x1b\r\r\r\r\r\r\r\r\r\r\r' -'\r11#\r\x1b\x1b\x1b\x1b\x1b\x1b\x1b\r\x1b\r\x1b\x1b\x1b\r\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\r\x1b\x1b\x1b\x1b\x1b\x1b\x1b\r\x1b\x1b\r\x1b\x1b\x1b\x1b\x1b\r\r3\x1b##' -'#11111\r11#\r##4\r\r\x1b\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\x1b\r\r\r\r\rhhhhhhhhhh\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r' -'\r1##\r\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\r\r\x1b\x1b\r\r\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\r\x1b\x1b\x1b\x1b\x1b\x1b\x1b\r\x1b\x1b\r\r\x1b\x1b\x1b\x1b\r\r3\x1b#1' -'#111\r\r\r##\r\r##4\r\r\r\r\r\r\r\r1#\r\r\r\r\x1b\x1b\r\x1b\x1b\x1b\r\r\r\rhhhhhhhhhh\xcd\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r' -'\r\r1\x1b\r\x1b\x1b\x1b\x1b\x1b\x1b\r\r\r\x1b\x1b\x1b\r\x1b\x1b\x1b\x1b\r\r\r\x1b\x1b\r\x1b\r\x1b\x1b\r\r\r\x1b\x1b\r\r\r\x1b\x1b\x1b\r\r\r\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\r\x1b\x1b\x1b\r\r\r\r##' -'1##\r\r\r###\r###4\r\r\r\r\r\r\r\r\r#\r\r\r\r\r\r\r\r\r\r\r\r\r\r\rhhhhhhhhhsss\r\r\r\r\r\r\r\r\r\r\r\r\r' -'\r###\r\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\r\x1b\x1b\x1b\r\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\r\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\r\x1b\x1b\x1b\x1b\x1b\r\r\r\r11' -'1####\r111\r1114\r\r\r\r\r\r\rPQ\r\r\r\r\r\r\r\r\r\x1b\x1b\r\r\r\rhhhhhhhhhh\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r' -'\r\r##\r\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\r\x1b\x1b\x1b\r\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\r\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\r\x1b\x1b\x1b\x1b\x1b\r\r\r\r#1' -'#####\r1##\r##14\r\r\r\r\r\r\r##\r\r\r\r\r\r\r\x1b\r\x1b\x1b\r\r\r\rhhhhhhhhhh\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r' -'\r\r##\r\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\r\x1b\x1b\x1b\r\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\r\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\r\r\r\r##' -'#111\r\r###\r###4\r\r\r\r\r\r\r\r\r#\r\r\r\r\r\r\r\r\x1b\x1b\r\r\r\rhhhhhhhhhh\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r' -'\r\r##\r\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\r\r\r\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\r\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\r\x1b\r\r' -'\x1b\x1b\x1b\x1b\x1b\x1b\x1b\r\r\r4\r\r\r\r###111\r1\r########\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r##\x9e\r\r\r\r\r\r\r\r\r\r\r' -'\r\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b1\x1b\x1b1111RR4\r\r\r\r\xb1' -'\x1b\x1b\x1b\x1b\x1b\x1b\x171SSSS111\x9ehhhhhhhhhh\x9e\x9e\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r' -'\r\x1b\x1b\r\x1b\r\r\x1b\x1b\r\x1b\r\r\x1b\r\r\r\r\r\r\x1b\x1b\x1b\x1b\r\x1b\x1b\x1b\x1b\x1b\x1b\x1b\r\x1b\x1b\x1b\r\x1b\r\x1b\r\r\x1b\x1b\r\x1b\x1b\x1b\x1b1\x1b\x1b1111TT\r11\x1b\r\r' -'\x1b\x1b\x1b\x1b\x1b\r\x17\rUUUU11\r\rhhhhhhhhhh\r\r\x1b\x1b\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r' -'\x1b\xcd\xcd\xcd\x9e\x9e\x9e\x9e\x9e\x9e\x9e\x9e\x9e\x9e\x9e\x9e\x9e\x9e\x9e\xcd\xcd\xcd\xcd\xcdZZ\xcd\xcd\xcd\xcd\xcd\xcdhhhhhhhhhhssssssssss\xcdZ\xcdZ\xcdY\xa8\x87\xa8\x87##' -'\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\r\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\r\r\r\r\r\rVW1X11111WWWW1#' -'W1]]4\x9e]]\x1b\x1b\x1b\x1b\r\r\r\r11111111\r111111111111111111111111111111111111\r\xcd\xcd' -'\xcd\xcd\xcd\xcd\xcd\xcdZ\xcd\xcd\xcd\xcd\xcd\xcd\r\r\xcd\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r' -'\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\r\x1b\x1b\x1b\x1b\x1b\r\x1b\x1b\r#1111#1\r\r\r13#4\r\r\r\r\r\r' -'hhhhhhhhhh\x9e\x9e\x9e\x9e\x9e\x9e\x1b\x1b\x1b\x1b\x1b\x1b##11\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r' -'\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!' -'!!!!!!\r\r\r\r\r\r\r\r\r\r\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\r\r\x9e\r\r\r\r' -'\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c' -'\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\r\r\r\r\r\x1c\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b' -'\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\r\r\r\r\r\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b' -'\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\r\r\r\r\r\r' -'\x1b\x1b\x1b\x1b\x1b\x1b\x1b\r\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b' -'\x1b\x1b\x1b\x1b\x1b\x1b\x1b\r\x1b\r\x1b\x1b\x1b\x1b\r\r\x1b\x1b\x1b\x1b\x1b\x1b\x1b\r\x1b\r\x1b\x1b\x1b\x1b\r\r\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b' -'\x1b\x1b\x1b\x1b\x1b\x1b\x1b\r\x1b\r\x1b\x1b\x1b\x1b\r\r\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\r\x1b\r\x1b\x1b\x1b\x1b\r\r\x1b\x1b\x1b\x1b\x1b\x1b\x1b\r' -'\x1b\r\x1b\x1b\x1b\x1b\r\r\x1b\x1b\x1b\x1b\x1b\x1b\x1b\r\x1b\x1b\x1b\x1b\x1b\x1b\x1b\r\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\r\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b' -'\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\r\x1b\r\x1b\x1b\x1b\x1b\r\r\x1b\x1b\x1b\x1b\x1b\x1b\x1b\r\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b' -'\x1b\x1b\x1b\x1b\x1b\x1b\x1b\r\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\r\r\r\r\r\r\x9e\x9e\x9e\x9e\x9e\x9e\x9e\x9ehhhhhhhhhsssssssssss\r\r\r' -'\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b' -'\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\r\r\r\r\r\r\r\r\r\r\r' -'\r\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b' -'\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b' -'\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b' -'\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b' -'\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b' -'\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b' -'\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b' -'\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b' -'\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b' -'\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x9e\x9e\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\r\r\r\r\r\r\r\r\r' -'\xda\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\xa8\x87\r\r\r\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b' -'\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x9e\x9e\x9ekkk\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r' -'\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\r\x1b\x1b\x1b\x1b114\r\r\r\r\r\r\r\r\r\r\r\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b114\x9e\x9e\r\r\r\r\r\r\r\r\r' -'\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b11\r\r\r\r\r\r\r\r\r\r\r\r\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\r\x1b\x1b\x1b\r11\r\r\r\r\r\r\r\r\r\r\r\r' -'\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b###1111111##' -'######1##11111111141\x9e\x9e\x9e\x17\x9e\x9e\x9e\xb1\x1b\r\r\rhhhhhhhhhh\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r' -'\xa2\xa2\xa2\xa2\xa2\xa2\x83\xa2\xa2\xa2\xa2111\x05\rhhhhhhhhhh\r\r\r\r\r\r\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b' -'\x1b\x1b\x1b\x17\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\r\r\r\r\r\r\r\r' -'\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\\\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r' -'\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r' -'!\x12!\x12!\x12!\x12!\x12!\x12!\x12!\x12!\x12!\x12!\x12!\x12!\x12!\x12!\x12!\x12!\x12!\x12!\x12!\x12!\x12!\x12!\x12!\x12!\x12!\x12!\x12!\x12!\x12!\x12!\x12!\x12' -'!\x12!\x12!\x12!\x12!\x12!\x12!\x12!\x12!\x12!\x12!\x12!\x12!\x12!\x12!\x12!\x12!\x12!\x12!\x12!\x12!\x12!\x12!\x12!\x12!\x12!\x12!\x12!\x12!\x12!\x12!\x12!\x12' -'!\x12!\x12!\x12!\x12!\x12!\x12!\x12!\x12!\x12!\x12!\x12\x12\x12\x12\x12\x12\x12\r\r\r\r!\x12!\x12!\x12!\x12!\x12!\x12!\x12!\x12!\x12!\x12!\x12!\x12!\x12!\x12!\x12!\x12' -'!\x12!\x12!\x12!\x12!\x12!\x12!\x12!\x12!\x12!\x12!\x12!\x12!\x12!\x12!\x12!\x12!\x12!\x12!\x12!\x12!\x12!\x12!\x12!\x12!\x12!\x12!\x12!\x12!\x12\r\r\r\r\r\r' -'\x12\x12\x12\x12\x12\x12\x12\x12!!!!!!!!\x12\x12\x12\x12\x12\x12\r\r!!!!!!\r\r\x12\x12\x12\x12\x12\x12\x12\x12!!!!!!!!\x12\x12\x12\x12\x12\x12\x12\x12!!!!!!!!' -'\x12\x12\x12\x12\x12\x12\r\r!!!!!!\r\r\x12\x12\x12\x12\x12\x12\x12\x12\r!\r!\r!\r!\x12\x12\x12\x12\x12\x12\x12\x12!!!!!!!!\x12\x12\x12\x12\x12\x12\x12\x12\x12\x12\x12\x12\x12\x12\r\r' -'\x12\x12\x12\x12\x12\x12\x12\x12\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x12\x12\x12\x12\x12\x12\x12\x12\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x12\x12\x12\x12\x12\x12\x12\x12\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x12\x12\x12\x12\x12\r\x12\x12!!!!\x1e\xb6\x12\xb6' -'\xb6\xb6\x12\x12\x12\r\x12\x12!!!!\x1e\xb6\xb6\xb6\x12\x12\x12\x12\r\r\x12\x12!!!!\r\xb6\xb6\xb6\x12\x12\x12\x12\x12\x12\x12\x12!!!!!\xb6\xb6\xb6\r\r\x12\x12\x12\r\x12\x12!!!!\x1e\xb6\xb6\r' -'\xda\xda\xda\xda\xda\xda\xda\xda\xda\xda\xda\xd7\x05\x05\x06\n\x82\x83\x83\x82\x82\x82\x9f\xa2\x8e\x8c\xa8\x8f\x8e\x8c\xa8\x8f\x9f\x9f\x9f\xa2\x9f\x9f\x9f\x9f\xd5\xd6\x07\x0b\t\x08\x0c\xda\x99\x9b\x99\x99\x9b\x9f\xa2\xa2\xa2\x90\x8d\x9f\xa2\xa2\x9f|' -'|\xa2\xa2\xa2\xc4\xa9\x88\xa2\xa2\xa2\xa2\xa2\xa2\xa2\xa2\xa2\xa2\xa2\xc4\r\r\r\r\xa2\r\r\r\r\r\r\r\xda\x05\x05\x05\x05\r\r\r\r\r\r\x05\x05\x05\x05\x05\x05q\x12\r\roqqqqq\xbb\xbb\xc4\xa9\x88\x10' -'qooooqqqqq\xbb\xbb\xc4\xa9\x88\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\xb1\xb1\xb1\xb1\xb1\xb1\xb1\xb1\xb1\xb0\xb1\xb1\xae\xb1\xb1\xb1\xb1\xb1\r\r\r\r\r\r\r\r\r\r\r\r\r\r' -'\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r]]22]]]]222]]&&&&]&&&22]Z]2\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r' -'\xd2\xd2!\xcf\xd2\xcf\xd2!\xd2\xcf\x12!!!\x12\x12!!!\x10\xd2!\xcf\xd2\xd2!!!!!\xd2\xd2\xd2\xcf\xcf\xd2!\xd2\x1f\xd2!\xd2!\x1f!!\xcb\x12!!\xd2!\x12\x1b\x1b\x1b\x1b\x12\xd2\r\r\x12!!' -'\xc5\xc4\xc4\xc4\xc4!\x12\x12\x12\x12\xd2\xc4\r\r\r\r\r\r\ruuwwwwwwuuuuwiiiiiiiiiiiikkkkiiiiiiiiiikkkkkk' -'kkkj\r\r\r\r\r\r\r\r\r\r\r\r\xbf\xbf\xbf\xbf\xbf\xcf\xcf\xcf\xcf\xcf\xc4\xc4\xd2\xd2\xd2\xd2\xc4\xd2\xd2\xc4\xd2\xd2\xc4\xd2\xd2\xd2\xd2\xd2\xd2\xd2\xc4\xd2\xd2\xd2\xd2\xd2\xd2\xd2\xd2\xd2\xcf\xcf\xd2\xd2\xd2\xd2\xd2\xd2' -'\xd2\xd2\xd2\xd2\xd2\xd2\xd2\xd2\xd2\xd2\xd2\xd2\xd2\xd2\xc4\xc4\xd2\xd2\xbf\xd2\xbf\xd2\xd2\xd2\xd2\xd2\xd2\xd2\xd2\xd2\xd2\xd2\xd2\xd2\xd2\xd2\xd2\xd2\xd2\xcf\xd2\xd2\xd2\xd2\xd2\xd2\xd2\xd2\xd2\xd2\xd2\xd2\xc4\xc4\xc4\xc4\xc4\xc4\xc4\xc4\xc4\xc4\xc4\xc4' -'\xbf\xc5\xc0\xc0\xc5\xc4\xc4\xbf\xc0\xc5\xc5\xc0\xc5\xc5\xc4\xbf\xc4\xc0\xbb\xbb\xc4\xc0\xc5\xc4\xc4\xc4\xc0\xc5\xc5\xc0\xbf\xc0\xc0\xc5\xc5\xbf\xc5\xbf\xc5\xbf\xbf\xbf\xbf\xc0\xc0\xc5\xc0\xc5\xc5\xc5\xc5\xc5\xbf\xbf\xbf\xbf\xc4\xc5\xc4\xc5\xc0\xc0\xc5\xc5' -'\xc5\xc5\xc5\xc5\xc5\xc5\xc5\xc5\xc0\xc5\xc5\xc5\xc0\xc4\xc4\xc4\xc4\xc4\xc0\xc5\xc5\xc5\xc4\xc4\xc4\xc4\xc4\xc4\xc4\xc4\xc4\xc5\xc0\xbf\xc5\xc4\xc0\xc0\xc0\xc0\xc5\xc5\xc0\xc0\xc4\xc4\xc0\xc0\xc5\xc5\xc5\xc5\xc5\xc5\xc5\xc5\xc5\xc5\xc5\xc5\xc5\xc5\xc5\xc5' -'\xc5\xc5\xc0\xc0\xc5\xc5\xc0\xc0\xc5\xc5\xc5\xc5\xc5\xc4\xc4\xc5\xc5\xc5\xc5\xc4\xc4\xbf\xc4\xc4\xc5\xbf\xc4\xc4\xc4\xc4\xc4\xc4\xc4\xc4\xc5\xc5\xc4\xbf\xc5\xc5\xc5\xc5\xc5\xc5\xc5\xc5\xc5\xc5\xc5\xc5\xc5\xc5\xc5\xc5\xc5\xc5\xc5\xc4\xc4\xc4\xc4\xc4\xc5\xc0' -'\xc4\xc4\xc4\xc4\xc4\xc4\xc4\xc4\xc4\xc5\xc5\xc5\xc5\xc5\xc4\xc4\xc5\xc5\xc4\xc4\xc4\xc4\xc5\xc5\xc5\xc5\xc5\xc5\xc5\xc5\xc5\xc5\xc5\xc5\xc5\xc5\xc5\xc5\xc5\xc5\xc5\xc5\xc5\xc5\xc5\xc5\xc4\xc4\xc5\xc5\xc5\xc5\xc5\xc5\xc5\xc5\xc5\xc5\xc5\xc5\xc5\xc5\xc5\xc5' -'\xd2\xd2\xd2\xd2\xd2\xd2\xd2\xd2\xc5\xc5\xc5\xc5\xd2\xd2\xd2\xd2\xd2\xd2\xcf\xd2\xd2\xd2\xd2\xd2\xd2\xd2\xd2\xd2\xd2\xd2\xd2\xd2\xc5\xc5\xd2\xd2\xd2\xd2\xd2\xd2\xd2\xac\x8b\xd2\xd2\xd2\xd2\xd2\xd2\xd2\xd2\xd2\xd2\xd2\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd' -'\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xd2\xc4\xd2\xd2\xd2' -'\xd2\xd2\xd2\xd2\xd2\xd2\xd2\xd2\xd2\xd2\xd2\xd2\xd2\xd2\xd2\xd2\xd2\xd2\xd2\xd2\xd2\xcd\xd2\xd2\xd2\xd2\xd2\xc4\xc4\xc4\xc4\xc4\xc4\xc4\xc4\xc4\xc4\xc4\xc4\xc4\xc4\xc4\xc4\xc4\xc4\xc4\xc4\xc4\xc4\xc4\xc4\xc4\xa8\x87\xa2\xd2\xd2\xd2\xd2\xd2\xd2\xd2\xd2\xd2' -'\xd2\xd2\xd2\xd2\xd2\xd2\xd2\xd2\xd2\xd2\xd2\xd2\xd2\xd2\xd2\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r' -'\xd2\xd2\xd2\xd2\xd2\xd2\xd2\xd2\xd2\xd2\xd2\xd2\xd2\xd2\xd2\xd2\xd2\xd2\xd2\xd2\xd2\xd2\xd2\xd2\xd2\xd2\xd2\xd2\xd2\xd2\xd2\xd2\xd2\xd2\xd2\xd2\xd2\xd2\xd2\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r' -'\xd2\xd2\xd2\xd2\xd2\xd2\xd2\xd2\xd2\xd2\xd2\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\rnnnnnnnnnmmmmmmmmmmmnnnnnnnnnmmm' -'mmmmmmmmnnnnnnnnnmmmmmmmmmmm\xcc\xcc\xcc\xcc\xcc\xcc\xcc\xcc\xcc\xcc\xcc\xcc\xcc\xcc\xcc\xcc\xcc\xcc\xcc\xcc\xcc\xcc\xcc\xcc\xcc\xcc\xcc\xcc\xcc\xcc\xcc\xcc\xcc\xcc\xcc\xcc' -'\xcc\xcc\xcc\xcc\xcc\xcc\xcc\xcc\xcc\xcc\xcc\xcc\xcc\xcc\xcc\xcc\xcc\xcc\xcc\xcc\xcc\xcc\xcc\xcc\xcc\xcc\xcc\xcc\xcc\xcc\xcc\xcc\xcc\xcc\xcc\xcc\xcc\xcc\xcc\xcc\xcc\xccpuuuuuuuuuuvvvvvvvvvu\r' -'\xcf\xcf\xcf\xcf\xcf\xcf\xcf\xcf\xcf\xcf\xcf\xcf\xcf\xcf\xcf\xcf\xcf\xcf\xcf\xcf\xcf\xcf\xcf\xcf\xcf\xcf\xcf\xcf\xcf\xcf\xcf\xcf\xcf\xcf\xcf\xcf\xcf\xcf\xcf\xcf\xcf\xcf\xcf\xcf\xcf\xcf\xcf\xcf\xcf\xcf\xcf\xcf\xcf\xcf\xcf\xcf\xcf\xcf\xcf\xcf\xcf\xcf\xcf\xcf' -'\xcf\xcf\xcf\xcf\xcf\xcf\xcf\xcf\xcf\xcf\xcf\xcf\xd2\xd2\xd2\xd2\xcf\xcf\xcf\xcf\xcf\xcf\xcf\xcf\xcf\xcf\xcf\xcf\xcf\xcf\xcf\xcf\xcf\xcf\xcf\xcf\xcf\xcf\xcf\xcf\xcf\xcf\xcf\xcf\xcf\xcf\xcf\xcf\xcf\xcf\xcf\xcf\xd2\xd2\xd2\xd2\xd2\xd2\xd2\xd2\xd2\xd2\xd2\xd2' -'\xcf\xcf\xcf\xcf\xcf\xcf\xcf\xcf\xcf\xcf\xcf\xcf\xcf\xcf\xcf\xcf\xd2\xd2\xcf\xcf\xcf\xcf\xd2\xd2\xd2\xd2\xd2\xd2\xd2\xd2\xd2\xd2\xcf\xcf\xd2\xcf\xcf\xcf\xcf\xcf\xcf\xcf\xd2\xd2\xd2\xd2\xd2\xd2\xd2\xd2\xcf\xcf\xd2\xd2\xcf\xbf\xd2\xd2\xd2\xd2\xcf\xcf\xd2\xd2' -'\xcf\xbf\xd2\xd2\xd2\xd2\xcf\xcf\xcf\xd2\xd2\xcf\xd2\xd2\xcf\xcf\xcf\xcf\xd2\xd2\xd2\xd2\xd2\xd2\xd2\xd2\xd2\xd2\xd2\xd2\xd2\xd2\xd2\xd2\xcf\xcf\xcf\xcf\xd2\xd2\xd2\xd2\xd2\xd2\xd2\xd2\xd2\xcf\xd2\xd2\xd2\xd2\xd2\xd2\xd2\xd2\xc4\xc4\xc4\xc4\xc4\xc4\xc4\xc4' -'\xd2\xd2\xd2\xd2\xd2\xcf\xcf\xd2\xd2\xcf\xd2\xd2\xd2\xd2\xcf\xcf\xd2\xd2\xd2\xd2\r\r\xd2\xd2\r\xd2\xd2\xd2\xcf\xd2\xcf\xd2\xd2\xd2\xd2\xd2\xd2\xd2\xd2\xd2\xd2\xd2\xd2\xd2\xd2\xd2\xd2\xd2\xd2\xd2\xd2\xd2\xd2\xd2\xd2\xd2\xd2\xd2\xd2\xd2\xd2\xd2\xd2\xd2' -'\xcf\xd2\xcf\xd2\xd2\xd2\xd2\xd2\xd2\xd2\xd2\xd2\xd2\xd2\xd2\xd2\xd2\xd2\xd2\xd2\xd2\xd2\xd2\xd2\xd2\xd2\xd2\xd2\xd2\xd2\xd2\xd2\xcf\xcf\xd2\xcf\xcf\xcf\xd2\xcf\xcf\xcf\xcf\xd2\xcf\xcf\xd2\xbf\xd2\xd2\xd2\xd2\xd2\xd2\xd2\xd2\xd2\xd2\xd2\xd2\xd2\xd2\r\r' -'\xd2\xd2\xd2\xd2\xd2\xd2\xd2\xd2\xd2\xd2\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r' -'\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r' -'\r\xd2\xd2\xd2\xd2\r\xd2\xd2\xd2\xd2\r\r\xd2\xd2\xd2\xd2\xd2\xd2\xd2\xd2\xd2\xd2\xd2\xd2\xd2\xd2\xd2\xd2\xd2\xd2\xd2\xd2\xd2\xd2\xd2\xd2\xd2\xd2\xd2\xd2\r\xd2\xd2\xd2\xd2\xd2\xd2\xd2\xd2\xd2\xd2\xd2\xd2\xd2\xd2\xd2\xd2\xd2\xd2\xd2\xd2\xcf\xd2\xd2' -'\xd2\xd2\xd2\xd2\xd2\xd2\xd2\xd2\xd2\xd2\xd2\xd2\r\xd2\r\xd2\xd2\xd2\xd2\r\r\r\xd2\r\xd2\xd2\xd2\xd2\xd2\xd2\xd2\r\r\xd2\xd2\xd2\xd2\xd2\xd2\xd2\xa9\x88\xa9\x88\xa9\x88\xa9\x88\xa9\x88\xa9\x88\xa9\x88vvvvvvvvvu' -'xxxxxxxxxwxxxxxxxxxw\xd2\r\r\r\xd2\xd2\xd2\xd2\xd2\xd2\xd2\xd2\xd2\xd2\xd2\xd2\xd2\xd2\xd2\xd2\xd2\xd2\xd2\xd2\xd2\xd2\xd2\xd2\r\xd2\xd2\xd2\xd2\xd2\xd2\xd2\xd2\xd2\xd2\xd2\xd2\xd2\xd2\r' -'\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\xc4\xc4\xc4\xc5\xc5\xc5\xc5\xc4\xc4\xc4\xc4\xc4\xc5\xc5\xc5\xc4\xc4\xc4\xc5\xc5\xc5\xc5\xaa\x89\xaa\x89\xaa\x89\r\r\r\r\xc4\xc4\xc4\xc4\xc4\xc4\xc4\xc4\xc4\xc4\xc4\xc4\xc4\xc4\xc4\xc4' -'\xd2\xd2\xd2\xd2\xd2\xd2\xd2\xd2\xd2\xd2\xd2\xd2\xd2\xd2\xd2\xd2\xd2\xd2\xd2\xd2\xd2\xd2\xd2\xd2\xd2\xd2\xd2\xd2\xd2\xd2\xd2\xd2\xd2\xd2\xd2\xd2\xd2\xd2\xd2\xd2\xd2\xd2\xd2\xd2\xd2\xd2\xd2\xd2\xd2\xd2\xd2\xd2\xd2\xd2\xd2\xd2\xd2\xd2\xd2\xd2\xd2\xd2\xd2\xd2' -'\xd2\xd2\xd2\xd2\xd2\xd2\xd2\xd2\xd2\xd2\xd2\xd2\xd2\xd2\xd2\xd2\xd2\xd2\xd2\xd2\xd2\xd2\xd2\xd2\xd2\xd2\xd2\xd2\xd2\xd2\xd2\xd2\xd2\xd2\xd2\xd2\xd2\xd2\xd2\xd2\xd2\xd2\xd2\xd2\xd2\xd2\xd2\xd2\xd2\xd2\xd2\xd2\xd2\xd2\xd2\xd2\xd2\xd2\xd2\xd2\xd2\xd2\xd2\xd2' -'\xd2\xd2\xd2\xd2\xd2\xd2\xd2\xd2\xd2\xd2\xd2\xd2\xd2\xd2\xd2\xd2\xd2\xd2\xd2\xd2\xd2\xd2\xd2\xd2\xd2\xd2\xd2\xd2\xd2\xd2\xd2\xd2\xd2\xd2\xd2\xd2\xd2\xd2\xd2\xd2\xd2\xd2\xd2\xd2\xd2\xd2\xd2\xd2\xd2\xd2\xd2\xd2\xd2\xd2\xd2\xd2\xd2\xd2\xd2\xd2\xd2\xd2\xd2\xd2' -'\xd2\xd2\xd2\xd2\xd2\xd2\xd2\xd2\xd2\xd2\xd2\xd2\xd2\xd2\xd2\xd2\xd2\xd2\xd2\xd2\xd2\xd2\xd2\xd2\xd2\xd2\xd2\xd2\xd2\xd2\xd2\xd2\xd2\xd2\xd2\xd2\xd2\xd2\xd2\xd2\xd2\xd2\xd2\xd2\xd2\xd2\xd2\xd2\xd2\xd2\xd2\xd2\xd2\xd2\xd2\xd2\xd2\xd2\xd2\xd2\xd2\xd2\xd2\xd2' -'\xc4\xc4\xc4\xc4\xc4\xc4\xc4\xc4\xc4\xc4\xc4\xc4\xc4\xc4\xc4\xc4\xc4\xc4\xc4\xc4\xc4\xc4\xc4\xc4\xc4\xc4\xc4\xc4\xc4\xc4\xc4\xc4\xc4\xc4\xc4\xc4\xc4\xc4\xc4\xc4\xc4\xc4\xc4\xc4\xc4\xc4\xc4\xc4\xc4\xc4\xc4\xc4\xc4\xc4\xc4\xc4\xc4\xc4\xc4\xc4\xc4\xc4\xc4\xc4' -'\xc4\xc4\xc4\xc4\xc4\xc4\xc4\xc4\xc4\xc4\xc4\xc4\xc4\xc4\xc4\xc4\xc4\xc4\xc4\xc4\xc4\xc4\xc4\xc4\xc4\xc4\xc4\xc4\xc4\xc4\xc4\xc4\xc4\xc4\xc4\xc4\xc4\xc4\xc4\xc4\xc4\xc4\xc4\xc4\xc4\xc4\xc4\xc4\xc4\xc4\xc4\xc4\xc4\xc4\xc4\xc4\xc4\xc4\xc4\xc4\xc4\xc4\xc4\xc4' -'\xc4\xc4\xc4\xa9\x88\xaa\x89\xa9\x88\xa9\x88\xa9\x88\xa9\x88\xa9\x88\xa9\x88\xa9\x88\xa9\x88\xa9\x88\xc4\xc4\xc5\xc5\xc5\xc5\xc5\xc5\xc5\xc5\xc5\xc5\xc5\xc5\xc5\xc5\xc5\xc5\xc5\xc5\xc5\xc5\xc5\xc4\xc4\xc4\xc4\xc4\xc4\xc4\xc4\xc5\xc4\xc4\xc4\xc4\xc4\xc4\xc4' -'\xc5\xc5\xc5\xc5\xc5\xc5\xc4\xc4\xc4\xc5\xc4\xc4\xc4\xc4\xc5\xc5\xc5\xc5\xc5\xc4\xc5\xc5\xc4\xc4\xa9\x88\xa9\x88\xc5\xc4\xc4\xc4\xc4\xc5\xc4\xc5\xc5\xc5\xc4\xc4\xc5\xc5\xc4\xc4\xc4\xc4\xc4\xc4\xc4\xc4\xc4\xc4\xc5\xc5\xc5\xc5\xc5\xc5\xc4\xc4\xa9\x88\xc4\xc4' -'\xc4\xc4\xc4\xc4\xc4\xc4\xc4\xc4\xc4\xc4\xc5\xc5\xc5\xc5\xc5\xc5\xc5\xc5\xc5\xc5\xc5\xc5\xc5\xc5\xc5\xc5\xc5\xc5\xc5\xc4\xc5\xc5\xc5\xc5\xc4\xc4\xc5\xc4\xc5\xc4\xc4\xc5\xc4\xc5\xc5\xc5\xc5\xc4\xc4\xc4\xc4\xc4\xc5\xc5\xc4\xc4\xc4\xc4\xc4\xc4\xc5\xc5\xc5\xc4' -'\xc4\xc4\xc4\xc4\xc4\xc4\xc4\xc4\xc4\xc4\xc4\xc4\xc4\xc4\xc4\xc4\xc4\xc4\xc4\xc4\xc4\xc4\xc4\xc5\xc5\xc4\xc4\xc4\xc4\xc4\xc4\xc4\xc4\xc4\xc4\xc4\xc5\xc5\xc4\xc4\xc4\xc4\xc5\xc5\xc5\xc5\xc4\xc5\xc5\xc4\xc4\xc5\xc5\xc4\xc4\xc4\xc4\xc5\xc5\xc5\xc5\xc5\xc5\xc5' -'\xc5\xc5\xc5\xc5\xc5\xc5\xc5\xc5\xc5\xc5\xc5\xc5\xc5\xc5\xc5\xc5\xc5\xc5\xc5\xc5\xc5\xc5\xc5\xc5\xc5\xc5\xc5\xc5\xc5\xc5\xc5\xc5\xc5\xc5\xc5\xc5\xc4\xc4\xc5\xc5\xc5\xc5\xc5\xc5\xc5\xc5\xc4\xc5\xc5\xc5\xc5\xc5\xc5\xc5\xc5\xc5\xc5\xc5\xc5\xc5\xc5\xc5\xc5\xc5' -'\xc5\xc5\xc5\xc5\xc5\xc5\xc5\xc5\xc5\xc5\xc5\xc5\xc5\xc5\xc5\xc5\xc5\xc5\xc5\xc5\xc5\xc5\xc5\xc4\xc4\xc4\xc4\xc4\xc5\xc4\xc5\xc4\xc4\xc4\xc5\xc5\xc5\xc5\xc5\xc4\xc4\xc4\xc4\xc4\xc5\xc5\xc5\xc4\xc4\xc4\xc4\xc5\xc4\xc4\xc4\xc5\xc5\xc5\xc5\xc5\xc4\xc5\xc4\xc4' -'\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r' -'\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r' -'\xd4\xd4\xd4\xd4\xd4\xd4\xd4\xd4\xd4\xd4\xd4\xd4\xd4\xd4\xd4\xd4\xd4\xd4\xd4\xd4\xd4\xd4\xd4\xd4\xd4\xd4\r\xd4\xd4\xd4\xd4\xd4\xd4\xd4\xd4\xd4\xd4\xd4\xd4\xd4\xd4\xd4\xd4\xd4\xd4\xd4\xd4\xd4\xd4\xd4\xd4\xd4\xd4\xd4\xd4\xd4\xd4\xd4\xd4\xd4\xd4\xd4\xd4\xd4' -'\xd4\xd4\xd4\xd4\xd4\xd4\xd4\xd4\xd4\xd4\xd4\xd4\xd4\xd4\xd4\xd4\xd4\xd4\xd4\xd4\xd4\xd4\xd4\xd4\xd4\xd4\xd4\xd4\xd4\xd4\xd4\xd4\xd4\xd4\xd4\xd4\xd4\xd4\xd4\xd4\xd4\xd4\xd4\xd4\xd4\xd4\xd4\xd4\xd4\xd4\xd4\xd4\r\r\r\r\r\r\r\r\r\r\r\r' -'\xd4\xd4\xd4\xd4\xd4\xd4\xd4\xd4\xd4\xd4\xd4\xd4\xd4\xd4\xd4\xd4\xd4\xd4\xd4\xd4\xd4\xd4\xd4\xd4\xd4\xd4\xd4\xd4\xd4\xd4\xd4\xd4\xd4\xd4\xd4\xd4\xd4\xd4\xd4\xd4\xd4\xd4\xd4\xd4\xd4\xd4\xd4\xd4\xd4\xd4\xd4\xd4\xd4\xd4\xd4\xd4\xd4\xd4\xd4\xd4\xd4\xd4\xd4\xd4' -'\xd4\xd4\xd4\xd4\xd4\xd4\xd4\xd4\xd4\xd4\xd4\xd4\xd4\xd4\xd4\xd4\xd4\xd4\xd4\xd4\xd4\xd4\xd4\xd4\xd4\xd4\xd4\xd4\xd4\xd4\xd4\xd4\xd4\xd4\xd4\xd4\xd4\xd4\xd4\xd4\xd4\xd4\xd4\xd4\xd4\xd4\xd4\xd4\xd4\xd4\xd4\xd4\xd4\xd4\xd4\xd4\xd4\xd4\xd4\xd4\xd4\xd4\xd4\xd4' -'\xd4\xd4\xd4\xd4\xd4\xd4\xd4\xd4\xd4\xd4\xd4\xd4\xd4\xd4\xd4\xd4\xd4\xd4\xd4\xd4\xd4\xd4\xd4\xd4\xd4\xd4\xd4\xd4\xd4\xd4\xd4\xd4\xd4\xd4\xd4\xd4\xd4\xd4\xd4\xd4\xd4\xd4\xd4\xd4\xd4\xd4\xd4\xd4\xd4\xd4\xd4\xd4\xd4\xd4\xd4\xd4\xd4\xd4\xd4\xd4\xd4\xd4\xd4\xd4' -'\xd4\xd4\xd4\xd4\xd4\xd4\xd4\xd4\xd4\xd4\xd4\xd4\xd4\xd4\xd4\xd4\xd4\xd4\xd4\xd4\xd4\xd4\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\xd4\xd4\xd4\xd4\xd4\xd4\xd4\xd4\xd4\xd4\xd4\xd4\r\r\r\r' -'\xd9\xa4\xa4\xa4\xd4\x18\x1cl\xac\x8b\xac\x8b\xac\x8b\xac\x8b\xac\x8b\xd4\xd4\xac\x8b\xac\x8b\xac\x8b\xac\x8b\x84\xab\x8a\x8a\xd4lllllllll_bc`aa\x84\x18\x18\x18\x18\x18\xd4\xd4lll\x18\x1c\xa4\xd4\xd2' -'\r\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c' -'\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\r\r^^\xb8\xb8\x18\x18\x1c\x84\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c' -'\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c~\x18\x18\x18\x1c' -'\r\r\r\r\r\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\r\r\r\r\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c' -'\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c' -'\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\r\xce\xcetttt\xce\xce\xce\xce\xce\xce\xce\xce\xce\xce\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\r\r\r\r\r\r\r\r' -'\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c' -'\xce\xce\xce\xce\xce\xce\xce\xce\xce\xce\xce\xce\xce\xce\xce\xce\xce\xce\xce\xce\xce\xce\xce\xce\xce\xce\xce\xce\xce\r\r\rtttttttttt\xce\xce\xce\xce\xce\xce\xce\xce\xce\xce\xce\xce\xce\xce\xce\xce\xce\xce\xce\xce\xce\xce' -'\xce\xce\xce\xce\r\r\r\r\r\r\r\r\r\r\r\r\ryyyyyyyyyyyyyyy\xce\xce\xce\xce\xce\xce\xce\xce\xce\xce\xce\xce\xce\xce\xce\xce\xce\xce\xce\xce\xce\xce\xce\xce\xce\xce\xce\xce\r\r\r\xce' -'tttttttttt\xce\xce\xce\xce\xce\xce\xce\xce\xce\xce\xce\xce\xce\xce\xce\xce\xce\xce\xce\xce\xce\xce\xce\xce\xce\xce\xce\xce\xce\xce\xce\xce\xce\xce\xce\xce\xce\xce\xceyyyyyyyyyyyyyyy' -'\xce\xce\xce\xce\xce\xce\xce\xce\xce\xce\xce\xce\r\r\r\r\xce\xce\xce\xce\xce\xce\xce\xce\xce\xce\xce\xce\xce\xce\xce\xce\xce\xce\xce\xce\xce\xce\xce\xce\xce\xce\xce\xce\xce\xce\xce\xce\xce\xce\xce\xce\xce\xce\xce\xce\xce\xce\xce\xce\xce\xce\xce\r' -'\xce\xce\xce\xce\xce\xce\xce\xce\xce\xce\xce\xce\xce\xce\xce\xce\xce\xce\xce\xce\xce\xce\xce\xce\xce\xce\xce\xce\xce\xce\xce\xce\xce\xce\xce\xce\xce\xce\xce\xce\xce\xce\xce\xce\xce\xce\xce\xce\xce\xce\xce\xce\xce\xce\xce\xce\xce\xce\xce\xce\xce\xce\xce\xce' -'\xce\xce\xce\xce\xce\xce\xce\xce\xce\xce\xce\xce\xce\xce\xce\xce\xce\xce\xce\xce\xce\xce\xce\xce\xce\xce\xce\xce\xce\xce\xce\xce\xce\xce\xce\xce\xce\xce\xce\xce\xce\xce\xce\xce\xce\xce\xce\xce\xce\xce\xce\xce\xce\xce\xce\r\r\r\r\xce\xce\xce\xce\xce' -'\xce\xce\xce\xce\xce\xce\xce\xce\xce\xce\xce\xce\xce\xce\xce\xce\xce\xce\xce\xce\xce\xce\xce\xce\xce\xce\xce\xce\xce\xce\xce\xce\xce\xce\xce\xce\xce\xce\xce\xce\xce\xce\xce\xce\xce\xce\xce\xce\xce\xce\xce\xce\xce\xce\xce\xce\xce\xce\xce\xce\xce\xce\xce\xce' -'\xce\xce\xce\xce\xce\xce\xce\xce\xce\xce\xce\xce\xce\xce\xce\xce\xce\xce\xce\xce\xce\xce\xce\xce\xce\xce\xce\xce\xce\xce\r\r\xce\xce\xce\xce\xce\xce\xce\xce\xce\xce\xce\xce\xce\xce\xce\xce\xce\xce\xce\xce\xce\xce\xce\xce\xce\xce\xce\xce\xce\xce\xce\r' -'\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c' -'\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c' -'\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c' -'\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c' -'\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c' -'\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c' -'\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\r\r\r\r\r\r\r\r\r\r' -'\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r' -'\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c' -'\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c' -'\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r' -'\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r' -'\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c' -'\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c' -'\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\r\r\r\xd4\xd4\xd4\xd4\xd4\xd4\xd4\xd4\xd4\xd4\xd4\xd4\xd4\xd4\xd4\xd4\xd4\xd4\xd4\xd4\xd4\xd4\xd4\xd4\xd4\xd4\xd4\xd4\xd4\xd4\xd4\xd4\xd4\xd4\xd4\xd4\xd4\xd4\xd4\xd4\xd4\xd4\xd4\xd4\xd4\xd4\xd4\xd4' -'\xd4\xd4\xd4\xd4\xd4\xd4\xd4\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r' -'\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c' -'\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c' -'\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r' -'\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r' +'\x01\x01\x01\x01\x01\x01\x01\x01\x01\x02\x00\x02\x03\x00\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x00\x00\x00\x02\xe2\xa9\xa9\xa2\xb8\xa2\xa9\xa9\xb0\x91\xa9\xc2\x9d\x88\x9d\x9dnnnnnnnnnn\x9d\xa9\xcf\xce\xcf\xa9' +"\xa9''''''''''''''''''''''''''\xb0\xa9\x91\xbd\x85\xbd\x16\x16\x16\x16\x16\x16\x16\x16\x16\x16\x16\x16\x16\x16\x16\x16\x16\x16\x16\x16\x16\x16\x16\x16\x16\x16\xb0\xce\x91\xce\x01" +'\x01\x01\x01\x01\x01\x00\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\xdf\xa5\xb8\xb8\xb4\xb8\xdb\xd7\xba\xda\x13\x98\xce\x05\xd7\xbd\xd2\xc4vv\xba\x15\xd7\xa5\xbav\x13\x95|||\xa5' +'&&&&&&$&&&&&&&&&$&&&&&&\xc7$&&&&&$\x13\x13\x13\x15\x15\x15\x15\x13\x15\x13\x13\x13\x15\x13\x13\x15\x15\x13\x15\x13\x13\x15\x15\x15\xc7\x13\x13\x13\x15\x13\x15\x13\x15' +'&\x13&\x15&\x15&\x15&\x15&\x15&\x15&\x15&\x13&\x13&\x15&\x15&\x15&\x13&\x15&\x15&\x15&\x15&\x15$\x13&\x15&\x13&\x15&\x15&\x13$\x13&\x15&\x15\x13&\x15&\x15&\x15$' +'\x13$\x13&\x13&\x15&\x13\x13$\x13&\x13&\x15&\x15$\x13&\x15&\x15&\x15&\x15&\x15&\x15&\x15&\x15&\x15$\x13&\x15&\x13&\x15&\x15&\x15&\x15&\x15&\x15&&\x15&\x15&\x15\x15' +'\x15&&\x15&\x15&&\x15&&&\x15\x15&&&&\x15&&\x15&&&\x15\x15\x15&&\x15&&\x15&\x15&\x15&&\x15&\x15\x15&\x15&&\x15&&&\x15&\x15&&\x15\x15 &\x15\x15\x15' +' &#\x15&#\x15&#\x15&\x13&\x13&\x13&\x13&\x13&\x13&\x13&\x13\x15&\x15&\x15&\x15&\x15&\x15&\x15&\x15&\x15&\x15\x15&#\x15&\x15&&&\x15&\x15&\x15&\x15' +'&\x15&\x15&\x15&\x15&\x15&\x15&\x15&\x15&\x15&\x15&\x15&\x15&\x15&\x15&\x15&\x15&\x15&\x15&\x15&\x15&\x15&\x15&\x15&\x15&\x15&\x15\x15\x15\x15\x15\x15\x15&&\x15&&\x15' +'\x15&\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x15\x13\x15\x15\x15\x15\x15\x15\x15\x15\x15\x15\x15\x15\x15\x15\x15\x13\x15\x15\x15\x15\x15\x15\x15\x15\x15\x15\x15\x15\x15\x15\x15\x15\x15\x15\x15\x15\x15\x15\x15\x15\x15\x15\x15\x15\x15\x15' +'\x15\x15\x15\x15\x15\x15\x15\x15\x15\x15\x15\x15\x15\x15\x15\x15\x15\x15\x15\x15\x15\x15\x15\x15\x15\x15\x15\x15\x15\x15\x15\x15\x15\x15\x15\x15\x15\x15\x15\x15\x15\x15\x15\x15\x15\x15\x15\x15\x1a\x1a\x1a\x1a\x1a\x1a\x1a\x1a\x1a\x1d\x1d\x1a\x1a\x1a\x1a\x1a' +'\x1a\x1a\xbc\xbc\xba\xbc\x1d\x1c\x1d\x1c\x1c\x1c\x1d\x1c\x1d\x1d\x18\x1a\xbc\xbc\xbc\xbc\xbc\xbc\xba\xba\xba\xba\xbc\xba\xbc\xba\x1a\x1a\x1a\x1a\x1a\xbc\xbc\xbc\xbc\xbc\xbc\xbc\xbc\xbc\x1a\xbc\xbc\xbc\xbc\xbc\xbc\xbc\xbc\xbc\xbc\xbc\xbc\xbc\xbc\xbc\xbc\xbc' +'3333333333333333333334222241222220022220022222222222/////2222333' +'333337322233322.33322223422356656653333333333333\x0f\x0f\x0f\x0f\xbc\xbc\x0f\x0f\x0f\x0f\x1a\x0f\x0f\x0f\xa8\x0f' +'\x0f\x0f\x0f\x0f\xbc\xbc&\xa8&&&\x0f&\x0f&&\x15$$$$$$$$$$$$$$$$$\x0f$$$$$$$&&\x15\x15\x15\x15\x15\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13' +'\x13\x13\x15\x13\x13\x13\x13\x13\x13\x13\x15\x15\x15\x15\x15\x0f\x15\x15&&&\x15\x15\x15&\x15&\x15&\x15&\x15&\x15&\x15&\x15&\x15&\x15&\x15&\x15&\x15\x15\x15\x15\x15&\x15\xcc&\x15&&\x15\x15&&&' +'&$&&&&&&&&&&&&&&$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13' +'\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x13\x15\x13\x15\x15\x15\x15\x15\x15\x15\x15\x15\x15\x15\x15\x15\x15&\x15&\x15&\x15&\x15&\x15&\x15&\x15&\x15&\x15&\x15&\x15&\x15&\x15&\x15&\x15&\x15' +'&\x15\xd5dddd\x0f,,&\x15&\x15&\x15&\x15&\x15&\x15&\x15&\x15&\x15&\x15&\x15&\x15&\x15&\x15&\x15&\x15&\x15&\x15&\x15&\x15&\x15&\x15&\x15&\x15&\x15&\x15&\x15' +'&&\x15&\x15&\x15&\x15&\x15&\x15&\x15\x0f&\x15&\x15&\x15&\x15&\x15&\x15&\x15&\x15&\x15&\x15&\x15&\x15&\x15&\x15&\x15&\x15&\x15&\x15&\x15&\x15&\x15\x0f\x0f\x0f\x0f\x0f\x0f' +'&\x15&\x15&\x15&\x15&\x15&\x15&\x15&\x15\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f&&&&&&&&&&&&&&&' +'&&&&&&&&&&&&&&&&&&&&&&&\x0f\x0f\x1a\xa4\xa4\xa4\xa4\xa4\xa4\x0f\x15\x15\x15\x15\x15\x15\x15\x15\x15\x15\x15\x15\x15\x15\x15\x15\x15\x15\x15\x15\x15\x15\x15\x15\x15\x15\x15\x15\x15\x15\x15' +'\x15\x15\x15\x15\x15\x15\x15\x15\x0f\xa4\x8b\x0f\x0f\x0f\x0f\x0f\x0faddddadddbaddddddaaaaaaddaddbcd<=>?@ABCDE\x0fFGH\xabI' +'\xabJK\xabda\xabD\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f"""""""""""""""""""""""""""\x0f\x0f\x0f\x0f\x0f"""\xab\xab\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f' +'\x04\x04\x04\x04\x0f\x0f\x0f\x0f\x0f\x0f\x0f\xb3\x9c\x99\xda\xdadddddd\x0f\x0f\x0f\x0f\x0f\x99\x0f\x0f\x99\x99\x0f\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x0f\x0f\x0f\x0f\x0f' +'\x17\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1eMNOPQRSTddaadddddadd\x0fkkkkkkkkkk\xa1\x9a\x9a\x99\x1e\x1eU\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e' +'\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e' +'\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x99\x1eddddddd\x04,ddddad\x17\x17dd\xdaadda\x1e\x1emmmmmmmmmm\x1e\x1e\x1e\xd1\xd1\x1e' +'\x99\x99\x99\x99\x99\x99\x99\x99\x99\x99\x99\x99\x99\x99\x0f\x06\x1eV\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1edaddaddaaadaadad' +'ddadadadadd\x0f\x0f\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f' +'\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e88888888888\x1e\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f' +'\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f' +'\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f' +'\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f' +'\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f' +'\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f' +'\x0f88( \x0f\x0f: ((' +'(88888888((((;\x0f\x0f dadd\x0f\x0f\x0f 88\xa4\xa4oooooooooo\xa4\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f \x0f\x0f' +'\x0f8((\x0f \x0f\x0f \x0f\x0f \x0f \x0f \x0f\x0f\x0f \x0f\x0f: ((' +'(8888\x0f\x0f((\x0f\x0f((; \x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f(\x0f\x0f\x0f\x0f \x0f 88\x0f\x0foooooooooo \xb7\xb7yyyyxy\xd5\x0f\x0f\x0f\x0f\x0f' +'\x0f88(\x0f \x0f\x0f\x0f\x0f \x0f\x0f \x0f \x0f \x0f \x0f \x0f\x0f:\x0f((' +'(88\x0f\x0f\x0f\x0f88\x0f\x0f88;\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f \x0f \x0f\x0f\x0f\x0f\x0f\x0f\x0foooooooooo88 \x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f' +'\x0f88(\x0f \x0f \x0f \x0f \x0f \x0f \x0f\x0f: ((' +'(88888\x0f88(\x0f((;\x0f\x0f \x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f 88\x0f\x0foooooooooo\x0f\xb7\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f' +'\x0f8((\x0f \x0f\x0f \x0f\x0f \x0f \x0f \x0f \x0f\x0f: (8' +'(888\x0f\x0f\x0f((\x0f\x0f((;\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f8(\x0f\x0f\x0f\x0f \x0f \x0f\x0f\x0f\x0foooooooooo\xd5 \x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f' +'\x0f\x0f8 \x0f \x0f\x0f\x0f \x0f \x0f\x0f\x0f \x0f \x0f \x0f\x0f\x0f \x0f\x0f\x0f \x0f\x0f\x0f \x0f\x0f\x0f\x0f((' +'8((\x0f\x0f\x0f(((\x0f(((;\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f(\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0fooooooooooyyy\xda\xda\xda\xda\xda\xda\xb7\xda\x0f\x0f\x0f\x0f\x0f' +'\x0f(((\x0f \x0f \x0f \x0f \x0f \x0f\x0f\x0f\x0f88' +'8((((\x0f888\x0f888;\x0f\x0f\x0f\x0f\x0f\x0f\x0fWX\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f \x0f\x0f\x0f\x0foooooooooo\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f' +'\x0f\x0f((\x0f \x0f \x0f \x0f \x0f \x0f\x0f: (-' +'(((((\x0f-((\x0f((8;\x0f\x0f\x0f\x0f\x0f\x0f\x0f((\x0f\x0f\x0f\x0f\x0f\x0f\x0f \x0f \x0f\x0f\x0f\x0foooooooooo\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f' +'\x0f\x0f((\x0f \x0f \x0f \x0f \x0f\x0f\x0f\x0f((' +'(888\x0f\x0f(((\x0f(((;\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f(\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f \x0f\x0f\x0f\x0foooooooooo\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f' +'\x0f\x0f((\x0f \x0f\x0f\x0f \x0f \x0f \x0f\x0f' +' \x0f\x0f\x0f;\x0f\x0f\x0f\x0f(((888\x0f8\x0f((((((((\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f((\xa4\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f' +'\x0f 8 8888YY;\x0f\x0f\x0f\x0f\xb7' +' \x1a8ZZZZ888\xa4oooooooooo\xa4\xa4\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f' +'\x0f \x0f \x0f\x0f \x0f \x0f\x0f \x0f\x0f\x0f\x0f\x0f\x0f \x0f \x0f \x0f \x0f \x0f\x0f \x0f 8 8888[[\x0f88 \x0f\x0f' +' \x0f\x1a\x0f\\\\\\\\88\x0f\x0foooooooooo\x0f\x0f \x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f' +' \xd5\xd5\xd5\xa4\xa4\xa4\xa4\xa4\xa4\xa4\xa4\xa4\xa4\xa4\xa4\xa4\xa4\xa4\xd5\xd5\xd5\xd5\xd5aa\xd5\xd5\xd5\xd5\xd5\xd5ooooooooooyyyyyyyyyy\xd5a\xd5a\xd5`\xae\x8f\xae\x8f((' +' \x0f \x0f\x0f\x0f\x0f\x0f\x0f]^8_88888^^^^8(' +'^8dd;\xa4dd \x0f\x0f\x0f\x0f88888888\x0f888888888888888888888888888888888888\x0f\xd5\xd5' +'\xd5\xd5\xd5\xd5\xd5\xd5a\xd5\xd5\xd5\xd5\xd5\xd5\x0f\x0f\xd5\xa4\xa4\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f' +' \x0f \x0f \x0f(8888(8\x0f\x0f\x0f8:(;\x0f\x0f\x0f\x0f\x0f\x0f' +'oooooooooo\xa4\xa4\xa4\xa4\xa4\xa4 ((88\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f' +'\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&' +'&&&&&&\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f \xa4\x1a\x0f\x0f\x0f' +'!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!' +'!!!!!!!!!!!!!!!!!!!!!!!!!!\x0f\x0f\x0f\x0f\x0f! ' +' \x0f\x0f\x0f\x0f\x0f ' +' \x0f\x0f\x0f\x0f\x0f\x0f' +' ' +' \x0f \x0f\x0f \x0f \x0f \x0f\x0f ' +' \x0f \x0f\x0f \x0f \x0f\x0f \x0f' +' \x0f \x0f\x0f \x0f ' +' \x0f \x0f\x0f ' +' \x0f\x0f\x0f\x0fd\xd5\xa4\xa4\xa4\xa4\xa4\xa4\xa4\xa4zzzzzzzzzyyyyyyyyyyy\x0f\x0f\x0f' +' \xda\xda\xda\xda\xda\xda\xda\xda\xda\xda\x0f\x0f\x0f\x0f\x0f\x0f ' +' \x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f' +'\x0f ' +' ' +' ' +' ' +' ' +' ' +' ' +' ' +' ' +' \xa4\xa4 \x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f' +'\xe1 \xae\x8f\x0f\x0f\x0f ' +' \xa4\xa4\xa4rrr\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f' +' \x0f 88;\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f 88;\xa4\xa4\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f' +' 88\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f \x0f \x0f88\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f' +' \x07\x07(8888888((' +'((((((8((888888888;8\xa4\xa4\xa4\x1a\xa4\xa4\xa4\xb7 d\x0f\x0foooooooooo\x0f\x0f\x0f\x0f\x0f\x0f~~~~~~~~~~\x0f\x0f\x0f\x0f\x0f\x0f' +'\xa8\xa8\xa8\xa8\xa8\xa8\x8b\xa8\xa8\xa8\xa8888\xe1\x0foooooooooo\x0f\x0f\x0f\x0f\x0f\x0f ' +' \x1a \x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f' +' c\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f' +'\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f' +' \x0f\x0f\x0f888((((88+++\x0f\x0f\x0f\x0f((8((((((bda\x0f\x0f\x0f\x0f' +'\xda\x0f\x0f\x0f\xa8\xa8oooooooooo \x0f\x0f \x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f' +' \x0f\x0f\x0f\x0f\x0f\x0f((((((((((((((((' +'( ((\x0f\x0f\x0f\x0f\x0f\x0foooooooooo\x0f\x0f\x0f\x0f\xa8\xa8\xda\xda\xda\xda\xda\xda\xda\xda\xda\xda\xda\xda\xda\xda\xda\xda\xda\xda\xda\xda\xda\xda\xda\xda\xda\xda\xda\xda\xda\xda\xda\xda' +' da(((\x0f\x0f\xa4\xa4\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f' +'\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f' +'\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f' +'\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f' +'\x15\x15\x15\x15\x15\x15\x15\x15\x15\x15\x15\x15\x15\x15\x15\x15\x15\x15\x15\x15\x15\x15\x15\x15\x15\x15\x15\x15\x15\x15\x15\x15\x15\x15\x15\x15\x15\x15\x15\x15\x15\x15\x15\x15\x1a\x1a\x1a\x1a\x1a\x1a\x1a\x1a\x1a\x1a\x1a\x1a\x1a\x1a\x1a\x1a\x1a\x1a\x1a\x1a' +'\x1a\x1a\x1a\x1a\x1a\x1a\x1a\x1a\x1a\x1a\x1a\x1a\x1a\x1a\x1a\x1a\x1a\x1a\x1a\x1a\x1a\x1a\x1a\x1a\x1a\x1a\x1a\x1a\x1a\x1a\x1a\x1a\x1a\x1a\x15\x15\x15\x15\x15\x15\x15\x15\x15\x15\x15\x15\x15\x15\x15\x15\x15\x15\x15\x15\x15\x15\x1a\x15\x15\x15\x15\x15\x15\x15' +'\x15\x15\x15\x15\x15\x15\x15\x15\x15\x15\x15\x15\x15\x15\x15\x15\x15\x15\x15\x15\x15\x15\x15\x15\x15\x15\x15\x1a\x1a\x1a\x1a\x1a\x1a\x1a\x1a\x1a\x1a\x1a\x1a\x1a\x1a\x1a\x1a\x1a\x1a\x1a\x1a\x1a\x1a\x1a\x1a\x1a\x1a\x1a\x1a\x1a\x1a\x1a\x1a\x1a\x1a\x1a\x1a\x1a' +'ddad\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f' +'&\x15&\x15&\x15&\x15&\x15&\x15&\x15&\x15&\x15&\x15&\x15&\x15&\x15&\x15&\x15&\x15&\x15&\x15&\x15&\x15&\x15&\x15&\x15&\x15&\x15&\x15&\x15&\x15&\x15&\x15&\x15&\x15' +'&\x15&\x15&\x15&\x15&\x15&\x15&\x15&\x15&\x15&\x15&\x15&\x15&\x15&\x15&\x15&\x15&\x15&\x15&\x15&\x15&\x15&\x15&\x15&\x15&\x15&\x15&\x15&\x15&\x15&\x15&\x15&\x15' +'&\x15&\x15&\x15&\x15&\x15&\x15&\x15&\x15&\x15&\x15&\x15\x15\x15\x15\x15\x15\x15\x0f\x0f\x0f\x0f&\x15&\x15&\x15&\x15&\x15&\x15&\x15&\x15&\x15&\x15&\x15&\x15&\x15&\x15&\x15&\x15' +'&\x15&\x15&\x15&\x15&\x15&\x15&\x15&\x15&\x15&\x15&\x15&\x15&\x15&\x15&\x15&\x15&\x15&\x15&\x15&\x15&\x15&\x15&\x15&\x15&\x15&\x15&\x15&\x15&\x15\x0f\x0f\x0f\x0f\x0f\x0f' +'\x15\x15\x15\x15\x15\x15\x15\x15&&&&&&&&\x15\x15\x15\x15\x15\x15\x0f\x0f&&&&&&\x0f\x0f\x15\x15\x15\x15\x15\x15\x15\x15&&&&&&&&\x15\x15\x15\x15\x15\x15\x15\x15&&&&&&&&' +'\x15\x15\x15\x15\x15\x15\x0f\x0f&&&&&&\x0f\x0f\x15\x15\x15\x15\x15\x15\x15\x15\x0f&\x0f&\x0f&\x0f&\x15\x15\x15\x15\x15\x15\x15\x15&&&&&&&&\x15\x15\x15\x15\x15\x15\x15\x15\x15\x15\x15\x15\x15\x15\x0f\x0f' +'\x15\x15\x15\x15\x15\x15\x15\x15########\x15\x15\x15\x15\x15\x15\x15\x15########\x15\x15\x15\x15\x15\x15\x15\x15########\x15\x15\x15\x15\x15\x0f\x15\x15&&&&#\xbc\x15\xbc' +'\xbc\xbc\x15\x15\x15\x0f\x15\x15&&&&#\xbc\xbc\xbc\x15\x15\x15\x15\x0f\x0f\x15\x15&&&&\x0f\xbc\xbc\xbc\x15\x15\x15\x15\x15\x15\x15\x15&&&&&\xbc\xbc\xbc\x0f\x0f\x15\x15\x15\x0f\x15\x15&&&&#\xbc\xbc\x0f' +'\xe1\xe1\xe1\xe1\xe1\xe1\xe1\xe1\xe1\xe1\xe1\x06\x06\x06\x07\x0c\x8a\x8b\x8b\x8a\x8a\x8a\xa5\xa8\x96\x94\xae\x97\x96\x94\xae\x97\xa5\xa5\xa5\xa8\xa5\xa5\xa5\xa5\xdd\xde\x08\r\x0b\t\x0e\xdf\x9f\xa1\x9f\x9f\xa1\xa5\xa8\xa8\xa8\x98\x95\xa5\xa8\xa8\xa5\x84' +'\x84\xa8\xa8\xa8\xbf\xaf\x90\xa8\xa8\xa8\xa8\xa8\xa8\xa8\xa8\xa8\xa8\xa8\xcc\xa8\x84\xa8\xa8\xa8\xa8\xa8\xa8\xa8\xa8\xa8\xa8\xe1\x06\x06\x06\x06\x0f\x0f\x0f\x0f\x0f\x0f\x06\x06\x06\x06\x06\x06w\x15\x0f\x0fvwwwww\xc1\xc1\xcc\xaf\x90\x13' +'wvvvvwwwww\xc1\xc1\xcc\xaf\x90\x0f\x1a\x1a\x1a\x1a\x1a\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\xb7\xb7\xb7\xb7\xb7\xb7\xb7\xb7\xb7\xb6\xb7\xb7\xb4\xb7\xb7\xb7\xb7\xb7\xb7\xb7\xb7\xb7\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f' +'\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0fdd99dddd999dd,,,,d,,,99dad99\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f' +'\xda\xda&\xd7\xda\xd7\xda&\xda\xd7\x15&&&\x15\x15&&&\x13\xda&\xd7\xda\xda&&&&&\xda\xda\xda\xd7\xd7\xda&\xda$\xda&\xda&$&&\xd3\x15&&\xda&\x15 \x15\xda\xda\x15\x15&&' +'\xcd\xcc\xcc\xcc\xcc&\x15\x15\x15\x15\xda\xcc\xda\x0f\x0f\x0f\x0f\x0f\x0f||~~~~~~||||~pppppppppppprrrrpppppppppprrrrrr' +'rrrq\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\xc7\xc7\xc7\xc7\xc7\xd7\xd7\xd7\xd7\xd7\xcc\xcc\xda\xda\xda\xda\xcc\xda\xda\xcc\xda\xda\xcc\xda\xda\xda\xda\xda\xda\xda\xcc\xda\xda\xda\xda\xda\xda\xda\xda\xda\xd7\xd7\xda\xda\xda\xda\xda\xda' +'\xda\xda\xda\xda\xda\xda\xda\xda\xda\xda\xda\xda\xda\xda\xcc\xcc\xda\xda\xc7\xda\xc7\xda\xda\xda\xda\xda\xda\xda\xda\xda\xda\xda\xda\xda\xda\xda\xda\xda\xda\xd7\xda\xda\xda\xda\xda\xda\xda\xda\xda\xda\xda\xda\xcc\xcc\xcc\xcc\xcc\xcc\xcc\xcc\xcc\xcc\xcc\xcc' +'\xc7\xcd\xc8\xc8\xcd\xcc\xcc\xc7\xc8\xcd\xcd\xc8\xcd\xcd\xcc\xc7\xcc\xc8\xc1\xc5\xcc\xc8\xcd\xcc\xcc\xcc\xc8\xcd\xcd\xc8\xc7\xc8\xc8\xcd\xcd\xc7\xcd\xc7\xcd\xc7\xc7\xc7\xc7\xc8\xc8\xcd\xc8\xcd\xcd\xcd\xcd\xcd\xc7\xc7\xc7\xc7\xcc\xcd\xcc\xcd\xc8\xc8\xcd\xcd' +'\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xc8\xcd\xcd\xcd\xc8\xcc\xcc\xcc\xcc\xcc\xc8\xcd\xcd\xcd\xcc\xcc\xcc\xcc\xcc\xcc\xcc\xcc\xcc\xcd\xc8\xc7\xcd\xcc\xc8\xc8\xc8\xc8\xcd\xcd\xc8\xc8\xcc\xcc\xc8\xc8\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd' +'\xcd\xcd\xc8\xc8\xcd\xcd\xc8\xc8\xcd\xcd\xcd\xcd\xcd\xcc\xcc\xcd\xcd\xcd\xcd\xcc\xcc\xc7\xcc\xcc\xcd\xc7\xcc\xcc\xcc\xcc\xcc\xcc\xcc\xcc\xcd\xcd\xcc\xc7\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcc\xcc\xcc\xcc\xcc\xcd\xc8' +'\xcc\xcc\xcc\xcc\xcc\xcc\xcc\xcc\xcc\xcd\xcd\xcd\xcd\xcd\xcc\xcc\xcd\xcd\xcc\xcc\xcc\xcc\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcc\xcc\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd' +'\xda\xda\xda\xda\xda\xda\xda\xda\xcd\xcd\xcd\xcd\xda\xda\xda\xda\xda\xda\xd7\xda\xda\xda\xda\xda\xda\xda\xda\xda\xda\xda\xda\xda\xcd\xcd\xda\xda\xda\xda\xda\xda\xda\xb2\x93\xda\xda\xda\xda\xda\xda\xda\xda\xda\xda\xda\xd5\xd5\xd5\xd5\xd5\xd5\xd5\xd5\xd5\xd5' +'\xd5\xd5\xd5\xd5\xd5\xd5\xd5\xd5\xd5\xd5\xd5\xd5\xd5\xd5\xd5\xd5\xd5\xd5\xd5\xd5\xd5\xd5\xd5\xd5\xd5\xd5\xd5\xd5\xd5\xd5\xd5\xd5\xd5\xd5\xd5\xd5\xd5\xd5\xd5\xd5\xd5\xd5\xd5\xd5\xd5\xd5\xd5\xd5\xd5\xd5\xd5\xd5\xd5\xd5\xd5\xd5\xd5\xd5\xd5\xda\xcc\xda\xda\xda' +'\xda\xda\xda\xda\xda\xda\xda\xda\xda\xda\xda\xda\xda\xda\xda\xda\xda\xda\xda\xda\xda\xd5\xda\xda\xda\xda\xda\xcc\xcc\xcc\xcc\xcc\xcc\xcc\xcc\xcc\xcc\xcc\xcc\xcc\xcc\xcc\xcc\xcc\xcc\xcc\xcc\xcc\xcc\xcc\xcc\xcc\xae\x8f\xa8\xda\xda\xda\xda\xda\xda\xda\xda\xda' +'\xda\xda\xda\xda\xda\xda\xda\xda\xda\xda\xda\xda\xda\xda\xda\xda\xda\xda\xda\xda\xda\xda\xda\xda\xda\xda\xda\xda\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f' +'\xda\xda\xda\xda\xda\xda\xda\xda\xda\xda\xda\xda\xda\xda\xda\xda\xda\xda\xda\xda\xda\xda\xda\xda\xda\xda\xda\xda\xda\xda\xda\xda\xda\xda\xda\xda\xda\xda\xda\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f' +'\xda\xda\xda\xda\xda\xda\xda\xda\xda\xda\xda\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f}}}}}}}}}|||||||||||}}}}}}}}}|||' +'||||||||vvvvvvvvvuuuuuuuuuuu\xd4\xd4\xd4\xd4\xd4\xd4\xd4\xd4\xd4\xd4\xd4\xd4\xd4\xd4\xd4\xd4\xd4\xd4\xd4\xd4\xd4\xd4\xd4\xd4\xd4\xd4\xd4\xd4\xd4\xd4\xd4\xd4\xd4\xd4\xd4\xd4' +'\xd4\xd4\xd4\xd4\xd4\xd4\xd4\xd4\xd4\xd4\xd4\xd4\xd4\xd4\xd4\xd4\xd4\xd4\xd4\xd4\xd4\xd4\xd4\xd4\xd4\xd4\xd4\xd4\xd4\xd4\xd4\xd4\xd4\xd4\xd4\xd4\xd4\xd4\xd4\xd4\xd4\xd4\x7f||||||||||}}}}}}}}}|}' +'\xd7\xd7\xd7\xd7\xd7\xd7\xd7\xd7\xd7\xd7\xd7\xd7\xd7\xd7\xd7\xd7\xd7\xd7\xd7\xd7\xd7\xd7\xd7\xd7\xd7\xd7\xd7\xd7\xd7\xd7\xd7\xd7\xd7\xd7\xd7\xd7\xd7\xd7\xd7\xd7\xd7\xd7\xd7\xd7\xd7\xd7\xd7\xd7\xd7\xd7\xd7\xd7\xd7\xd7\xd7\xd7\xd7\xd7\xd7\xd7\xd7\xd7\xd7\xd7' +'\xd7\xd7\xd7\xd7\xd7\xd7\xd7\xd7\xd7\xd7\xd7\xd7\xda\xda\xda\xda\xd7\xd7\xd7\xd7\xd7\xd7\xd7\xd7\xd7\xd7\xd7\xd7\xd7\xd7\xd7\xd7\xd7\xd7\xd7\xd7\xd7\xd7\xd7\xd7\xd7\xd7\xd7\xd7\xd7\xd7\xd7\xd7\xd7\xd7\xd7\xd7\xda\xda\xda\xda\xda\xda\xda\xda\xda\xda\xda\xda' +'\xd7\xd7\xd7\xd7\xd7\xd7\xd7\xd7\xd7\xd7\xd7\xd7\xd7\xd7\xd7\xd7\xda\xda\xd7\xd7\xd7\xd7\xda\xda\xda\xda\xda\xda\xda\xda\xda\xda\xd7\xd7\xda\xd7\xd7\xd7\xd7\xd7\xd7\xd7\xda\xda\xda\xda\xda\xda\xda\xda\xd7\xd7\xda\xda\xd7\xc7\xda\xda\xda\xda\xd7\xd7\xda\xda' +'\xd7\xc7\xda\xda\xda\xda\xd7\xd7\xd7\xda\xda\xd7\xda\xda\xd7\xd7\xd7\xd7\xda\xda\xda\xda\xda\xda\xda\xda\xda\xda\xda\xda\xda\xda\xda\xda\xd7\xd7\xd7\xd7\xda\xda\xda\xda\xda\xda\xda\xda\xda\xd7\xda\xda\xda\xda\xda\xda\xda\xda\xcc\xcc\xcc\xcc\xcc\xcc\xcc\xcc' +'\xda\xda\xda\xda\xda\xd7\xd7\xda\xda\xd7\xda\xda\xda\xda\xd7\xd7\xda\xda\xda\xda\xd7\xd7\xda\xda\xda\xda\xda\xda\xd7\xda\xd7\xda\xda\xda\xda\xda\xda\xda\xda\xda\xda\xda\xda\xda\xda\xda\xda\xda\xda\xda\xda\xda\xda\xda\xda\xda\xda\xda\xda\xda\xda\xda\xda\xda' +'\xd7\xda\xd7\xda\xda\xda\xda\xda\xda\xda\xda\xda\xda\xda\xda\xda\xda\xda\xda\xda\xda\xda\xda\xda\xda\xda\xda\xda\xda\xda\xda\xda\xd7\xd7\xda\xd7\xd7\xd7\xda\xd7\xd7\xd7\xd7\xda\xd7\xd7\xda\xc7\xda\xda\xda\xda\xda\xda\xda\xda\xda\xda\xda\xda\xda\xda\xda\xda' +'\xda\xda\xda\xda\xda\xda\xda\xda\xda\xda\xda\xda\xda\xda\xda\xda\xda\xda\xda\xda\xda\xda\xda\xda\xda\xda\xda\xda\xda\x0f\x0f\x0f\xda\xda\xda\xda\xda\xda\xda\xda\xda\xda\xda\xda\xd5\xda\xda\xda\xda\xda\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f' +'\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f' +'\x0f\xda\xda\xda\xda\x0f\xda\xda\xda\xda\x0f\x0f\xda\xda\xda\xda\xda\xda\xda\xda\xda\xda\xda\xda\xda\xda\xda\xda\xda\xda\xda\xda\xda\xda\xda\xda\xda\xda\xda\xda\x0f\xda\xda\xda\xda\xda\xda\xda\xda\xda\xda\xda\xda\xda\xda\xda\xda\xda\xda\xda\xda\xd7\xda\xda' +'\xda\xda\xda\xda\xda\xda\xda\xda\xda\xda\xda\xda\x0f\xda\x0f\xda\xda\xda\xda\x0f\x0f\x0f\xda\x0f\xda\xda\xda\xda\xda\xda\xda\x0f\x0f\xda\xda\xda\xda\xda\xda\xda\xaf\x90\xaf\x90\xaf\x90\xaf\x90\xaf\x90\xaf\x90\xaf\x90}}}}}}}}}|' +'\x7f\x7f\x7f\x7f\x7f\x7f\x7f\x7f\x7f~\x7f\x7f\x7f\x7f\x7f\x7f\x7f\x7f\x7f~\xda\x0f\x0f\x0f\xda\xda\xda\xda\xda\xda\xda\xda\xda\xda\xda\xda\xda\xda\xda\xda\xda\xda\xda\xda\xda\xda\xda\xda\x0f\xda\xda\xda\xda\xda\xda\xda\xda\xda\xda\xda\xda\xda\xda\x0f' +'\xcd\xcc\xcc\xcd\xcd\xaf\x90\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\xcc\xcc\xcc\xcd\xcd\xcd\xcd\xcc\xcc\xcc\xcc\xcc\xcd\xcd\xcd\xcc\xcc\xcc\xcd\xcd\xcd\xcd\xb0\x91\xb0\x91\xb0\x91\x0f\x0f\x0f\x0f\xcc\xcc\xcc\xcc\xcc\xcc\xcc\xcc\xcc\xcc\xcc\xcc\xcc\xcc\xcc\xcc' +'\xd5\xd5\xd5\xd5\xd5\xd5\xd5\xd5\xd5\xd5\xd5\xd5\xd5\xd5\xd5\xd5\xd5\xd5\xd5\xd5\xd5\xd5\xd5\xd5\xd5\xd5\xd5\xd5\xd5\xd5\xd5\xd5\xd5\xd5\xd5\xd5\xd5\xd5\xd5\xd5\xd5\xd5\xd5\xd5\xd5\xd5\xd5\xd5\xd5\xd5\xd5\xd5\xd5\xd5\xd5\xd5\xd5\xd5\xd5\xd5\xd5\xd5\xd5\xd5' +'\xd5\xd5\xd5\xd5\xd5\xd5\xd5\xd5\xd5\xd5\xd5\xd5\xd5\xd5\xd5\xd5\xd5\xd5\xd5\xd5\xd5\xd5\xd5\xd5\xd5\xd5\xd5\xd5\xd5\xd5\xd5\xd5\xd5\xd5\xd5\xd5\xd5\xd5\xd5\xd5\xd5\xd5\xd5\xd5\xd5\xd5\xd5\xd5\xd5\xd5\xd5\xd5\xd5\xd5\xd5\xd5\xd5\xd5\xd5\xd5\xd5\xd5\xd5\xd5' +'\xd5\xd5\xd5\xd5\xd5\xd5\xd5\xd5\xd5\xd5\xd5\xd5\xd5\xd5\xd5\xd5\xd5\xd5\xd5\xd5\xd5\xd5\xd5\xd5\xd5\xd5\xd5\xd5\xd5\xd5\xd5\xd5\xd5\xd5\xd5\xd5\xd5\xd5\xd5\xd5\xd5\xd5\xd5\xd5\xd5\xd5\xd5\xd5\xd5\xd5\xd5\xd5\xd5\xd5\xd5\xd5\xd5\xd5\xd5\xd5\xd5\xd5\xd5\xd5' +'\xd5\xd5\xd5\xd5\xd5\xd5\xd5\xd5\xd5\xd5\xd5\xd5\xd5\xd5\xd5\xd5\xd5\xd5\xd5\xd5\xd5\xd5\xd5\xd5\xd5\xd5\xd5\xd5\xd5\xd5\xd5\xd5\xd5\xd5\xd5\xd5\xd5\xd5\xd5\xd5\xd5\xd5\xd5\xd5\xd5\xd5\xd5\xd5\xd5\xd5\xd5\xd5\xd5\xd5\xd5\xd5\xd5\xd5\xd5\xd5\xd5\xd5\xd5\xd5' +'\xcc\xcc\xcc\xcc\xcc\xcc\xcc\xcc\xcc\xcc\xcc\xcc\xcc\xcc\xcc\xcc\xcc\xcc\xcc\xcc\xcc\xcc\xcc\xcc\xcc\xcc\xcc\xcc\xcc\xcc\xcc\xcc\xcc\xcc\xcc\xcc\xcc\xcc\xcc\xcc\xcc\xcc\xcc\xcc\xcc\xcc\xcc\xcc\xcc\xcc\xcc\xcc\xcc\xcc\xcc\xcc\xcc\xcc\xcc\xcc\xcc\xcc\xcc\xcc' +'\xcc\xcc\xcc\xcc\xcc\xcc\xcc\xcc\xcc\xcc\xcc\xcc\xcc\xcc\xcc\xcc\xcc\xcc\xcc\xcc\xcc\xcc\xcc\xcc\xcc\xcc\xcc\xcc\xcc\xcc\xcc\xcc\xcc\xcc\xcc\xcc\xcc\xcc\xcc\xcc\xcc\xcc\xcc\xcc\xcc\xcc\xcc\xcc\xcc\xcc\xcc\xcc\xcc\xcc\xcc\xcc\xcc\xcc\xcc\xcc\xcc\xcc\xcc\xcc' +'\xcc\xcc\xcc\xaf\x90\xb0\x91\xaf\x90\xaf\x90\xaf\x90\xaf\x90\xaf\x90\xaf\x90\xaf\x90\xaf\x90\xaf\x90\xcc\xcc\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcc\xcc\xcc\xcc\xcc\xcc\xcc\xcc\xcd\xcc\xcc\xcc\xcc\xcc\xcc\xcc' +'\xcd\xcd\xcd\xcd\xcd\xcd\xcc\xcc\xcc\xcd\xcc\xcc\xcc\xcc\xcd\xcd\xcd\xcd\xcd\xcc\xcd\xcd\xcc\xcc\xaf\x90\xaf\x90\xcd\xcc\xcc\xcc\xcc\xcd\xcc\xcd\xcd\xcd\xcc\xcc\xcd\xcd\xcc\xcc\xcc\xcc\xcc\xcc\xcc\xcc\xcc\xcc\xcd\xcd\xcd\xcd\xcd\xcd\xcc\xcc\xaf\x90\xcc\xcc' +'\xcc\xcc\xcc\xcc\xcc\xcc\xcc\xcc\xcc\xcc\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcc\xcd\xcd\xcd\xcd\xcc\xcc\xcd\xcc\xcd\xcc\xcc\xcd\xcc\xcd\xcd\xcd\xcd\xcc\xcc\xcc\xcc\xcc\xcd\xcd\xcc\xcc\xcc\xcc\xcc\xcc\xcd\xcd\xcd\xcc' +'\xcc\xcc\xcc\xcc\xcc\xcc\xcc\xcc\xcc\xcc\xcc\xcc\xcc\xcc\xcc\xcc\xcc\xcc\xcc\xcc\xcc\xcc\xcc\xcd\xcd\xcc\xcc\xcc\xcc\xcc\xcc\xcc\xcc\xcc\xcc\xcc\xcd\xcd\xcc\xcc\xcc\xcc\xcd\xcd\xcd\xcd\xcc\xcd\xcd\xcc\xcc\xcd\xcd\xcc\xcc\xcc\xcc\xcd\xcd\xcd\xcd\xcd\xcd\xcd' +'\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcc\xcc\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcc\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd' +'\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcc\xcc\xcc\xcc\xcc\xcd\xcc\xcd\xcc\xcc\xcc\xcd\xcd\xcd\xcd\xcd\xcc\xcc\xcc\xcc\xcc\xcd\xcd\xcd\xcc\xcc\xcc\xcc\xcd\xcc\xcc\xcc\xcd\xcd\xcd\xcd\xcd\xcc\xcd\xcc\xcc' +'\xda\xda\xda\xda\xda\xda\xda\xda\xda\xda\xda\xda\xda\xda\xda\xda\xda\xda\xda\xda\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f' +'\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f' +'\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f' +'\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f' +'&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&\x0f\x15\x15\x15\x15\x15\x15\x15\x15\x15\x15\x15\x15\x15\x15\x15\x15' +'\x15\x15\x15\x15\x15\x15\x15\x15\x15\x15\x15\x15\x15\x15\x15\x15\x15\x15\x15\x15\x15\x15\x15\x15\x15\x15\x15\x15\x15\x15\x15\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f' +'&\x15&\x15&\x15&\x15&\x15&\x15&\x15&\x15&\x15&\x15&\x15&\x15&\x15&\x15&\x15&\x15&\x15&\x15&\x15&\x15&\x15&\x15&\x15&\x15&\x15&\x15&\x15&\x15&\x15&\x15&\x15&\x15' +'&\x15&\x15&\x15&\x15&\x15&\x15&\x15&\x15&\x15&\x15&\x15&\x15&\x15&\x15&\x15&\x15&\x15&\x15\x15\xda\xda\xda\xda\xda\xda\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\xa8\xa8\xa8\xa8~\xa8\xa8' +'\x15\x15\x15\x15\x15\x15\x15\x15\x15\x15\x15\x15\x15\x15\x15\x15\x15\x15\x15\x15\x15\x15\x15\x15\x15\x15\x15\x15\x15\x15\x15\x15\x15\x15\x15\x15\x15\x15\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f ' +' \x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x1a\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f' +' \x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f \x0f \x0f \x0f \x0f' +' \x0f \x0f \x0f \x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f' +'\xa8\xa8\x98\x95\x98\x95\xa8\xa8\xa8\x98\x95\xa8\x98\x95\xa8\xa8\xa8\xa8\xa8\xa8\xa8\xa8\xa8\x8b\x0f\x0f\x0f\x0f\x98\x95\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f' +'\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f' +'\xdc\xdc\xdc\xdc\xdc\xdc\xdc\xdc\xdc\xdc\xdc\xdc\xdc\xdc\xdc\xdc\xdc\xdc\xdc\xdc\xdc\xdc\xdc\xdc\xdc\xdc\x0f\xdc\xdc\xdc\xdc\xdc\xdc\xdc\xdc\xdc\xdc\xdc\xdc\xdc\xdc\xdc\xdc\xdc\xdc\xdc\xdc\xdc\xdc\xdc\xdc\xdc\xdc\xdc\xdc\xdc\xdc\xdc\xdc\xdc\xdc\xdc\xdc\xdc' +'\xdc\xdc\xdc\xdc\xdc\xdc\xdc\xdc\xdc\xdc\xdc\xdc\xdc\xdc\xdc\xdc\xdc\xdc\xdc\xdc\xdc\xdc\xdc\xdc\xdc\xdc\xdc\xdc\xdc\xdc\xdc\xdc\xdc\xdc\xdc\xdc\xdc\xdc\xdc\xdc\xdc\xdc\xdc\xdc\xdc\xdc\xdc\xdc\xdc\xdc\xdc\xdc\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f' +'\xdc\xdc\xdc\xdc\xdc\xdc\xdc\xdc\xdc\xdc\xdc\xdc\xdc\xdc\xdc\xdc\xdc\xdc\xdc\xdc\xdc\xdc\xdc\xdc\xdc\xdc\xdc\xdc\xdc\xdc\xdc\xdc\xdc\xdc\xdc\xdc\xdc\xdc\xdc\xdc\xdc\xdc\xdc\xdc\xdc\xdc\xdc\xdc\xdc\xdc\xdc\xdc\xdc\xdc\xdc\xdc\xdc\xdc\xdc\xdc\xdc\xdc\xdc\xdc' +'\xdc\xdc\xdc\xdc\xdc\xdc\xdc\xdc\xdc\xdc\xdc\xdc\xdc\xdc\xdc\xdc\xdc\xdc\xdc\xdc\xdc\xdc\xdc\xdc\xdc\xdc\xdc\xdc\xdc\xdc\xdc\xdc\xdc\xdc\xdc\xdc\xdc\xdc\xdc\xdc\xdc\xdc\xdc\xdc\xdc\xdc\xdc\xdc\xdc\xdc\xdc\xdc\xdc\xdc\xdc\xdc\xdc\xdc\xdc\xdc\xdc\xdc\xdc\xdc' +'\xdc\xdc\xdc\xdc\xdc\xdc\xdc\xdc\xdc\xdc\xdc\xdc\xdc\xdc\xdc\xdc\xdc\xdc\xdc\xdc\xdc\xdc\xdc\xdc\xdc\xdc\xdc\xdc\xdc\xdc\xdc\xdc\xdc\xdc\xdc\xdc\xdc\xdc\xdc\xdc\xdc\xdc\xdc\xdc\xdc\xdc\xdc\xdc\xdc\xdc\xdc\xdc\xdc\xdc\xdc\xdc\xdc\xdc\xdc\xdc\xdc\xdc\xdc\xdc' +'\xdc\xdc\xdc\xdc\xdc\xdc\xdc\xdc\xdc\xdc\xdc\xdc\xdc\xdc\xdc\xdc\xdc\xdc\xdc\xdc\xdc\xdc\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\xdc\xdc\xdc\xdc\xdc\xdc\xdc\xdc\xdc\xdc\xdc\xdc\x0f\x0f\x0f\x0f' +'\xe0\xaa\xaa\xaa\xdc\x1b!s\xb2\x93\xb2\x93\xb2\x93\xb2\x93\xb2\x93\xdc\xdc\xb2\x93\xb2\x93\xb2\x93\xb2\x93\x8c\xb1\x92\x92\xdcsssssssssfijghh\x8c\x1b\x1b\x1b\x1b\x1b\xdc\xdcsss\x1b!\xaa\xdc\xda' +'\x0f!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!' +'!!!!!!!!!!!!!!!!!!!!!!!\x0f\x0fee\xbe\xbe\x1b\x1b!\x8c!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!' +'!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!\xaa\x1b\x1b\x1b!' +'\x0f\x0f\x0f\x0f\x0f!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!\x0f\x0f\x0f\x0f!!!!!!!!!!!!!!!' +'!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!' +'!!!!!!!!!!!!!!!\x0f\xd6\xd6{{{{\xd6\xd6\xd6\xd6\xd6\xd6\xd6\xd6\xd6\xd6!!!!!!!!!!!!!!!!!!!!!!!!\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f' +'\xdc\xdc\xdc\xdc\xdc\xdc\xdc\xdc\xdc\xdc\xdc\xdc\xdc\xdc\xdc\xdc\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f!!!!!!!!!!!!!!!!' +'\xd6\xd6\xd6\xd6\xd6\xd6\xd6\xd6\xd6\xd6\xd6\xd6\xd6\xd6\xd6\xd6\xd6\xd6\xd6\xd6\xd6\xd6\xd6\xd6\xd6\xd6\xd6\xd6\xd6\xdc\xdc\x0f{{{{{{{{{{\xd6\xd6\xd6\xd6\xd6\xd6\xd6\xd6\xd6\xd6\xd6\xd6\xd6\xd6\xd6\xd6\xd6\xd6\xd6\xd6\xd6\xd6' +'\xd6\xd6\xd6\xd6\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\xdc\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\xd6\xd6\xd6\xd6\xd6\xd6\xd6\xd6\xd6\xd6\xd6\xd6\xd6\xd6\xd6\xd6\xd6\xd6\xd6\xd6\xd6\xd6\xd6\xd6\xd6\xd6\xd6\xd6\xdc\xdc\xdc\xd6' +'{{{{{{{{{{\xd6\xd6\xd6\xd6\xd6\xd6\xd6\xd6\xd6\xd6\xd6\xd6\xd6\xd6\xd6\xd6\xd6\xd6\xd6\xd6\xd6\xd6\xd6\xd6\xd6\xd6\xd6\xd6\xd6\xd6\xd6\xd6\xd6\xd6\xd6\xd6\xd6\xd6\xd6\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80' +'\xd6\xd6\xd6\xd6\xd6\xd6\xd6\xd6\xd6\xd6\xd6\xd6\xdc\xdc\xdc\xdc\xd6\xd6\xd6\xd6\xd6\xd6\xd6\xd6\xd6\xd6\xd6\xd6\xd6\xd6\xd6\xd6\xd6\xd6\xd6\xd6\xd6\xd6\xd6\xd6\xd6\xd6\xd6\xd6\xd6\xd6\xd6\xd6\xd6\xd6\xd6\xd6\xd6\xd6\xd6\xd6\xd6\xd6\xd6\xd6\xd6\xd6\xd6\x0f' +'\xd6\xd6\xd6\xd6\xd6\xd6\xd6\xd6\xd6\xd6\xd6\xd6\xd6\xd6\xd6\xd6\xd6\xd6\xd6\xd6\xd6\xd6\xd6\xd6\xd6\xd6\xd6\xd6\xd6\xd6\xd6\xd6\xd6\xd6\xd6\xd6\xd6\xd6\xd6\xd6\xd6\xd6\xd6\xd6\xd6\xd6\xd6\xd6\xd6\xd6\xd6\xd6\xd6\xd6\xd6\xd6\xd6\xd6\xd6\xd6\xd6\xd6\xd6\xd6' +'\xd6\xd6\xd6\xd6\xd6\xd6\xd6\xd6\xd6\xd6\xd6\xd6\xd6\xd6\xd6\xd6\xd6\xd6\xd6\xd6\xd6\xd6\xd6\xd6\xd6\xd6\xd6\xd6\xd6\xd6\xd6\xd6\xd6\xd6\xd6\xd6\xd6\xd6\xd6\xd6\xd6\xd6\xd6\xd6\xd6\xd6\xd6\xd6\xd6\xd6\xd6\xd6\xd6\xd6\xd6\xdc\xdc\xdc\xdc\xd6\xd6\xd6\xd6\xd6' +'\xd6\xd6\xd6\xd6\xd6\xd6\xd6\xd6\xd6\xd6\xd6\xd6\xd6\xd6\xd6\xd6\xd6\xd6\xd6\xd6\xd6\xd6\xd6\xd6\xd6\xd6\xd6\xd6\xd6\xd6\xd6\xd6\xd6\xd6\xd6\xd6\xd6\xd6\xd6\xd6\xd6\xd6\xd6\xd6\xd6\xd6\xd6\xd6\xd6\xd6\xd6\xd6\xd6\xd6\xd6\xd6\xd6\xd6\xd6\xd6\xd6\xd6\xd6\xd6' +'\xd6\xd6\xd6\xd6\xd6\xd6\xd6\xd6\xd6\xd6\xd6\xd6\xd6\xd6\xd6\xd6\xd6\xd6\xd6\xd6\xd6\xd6\xd6\xd6\xd6\xd6\xd6\xd6\xd6\xd6\xdc\xdc\xd6\xd6\xd6\xd6\xd6\xd6\xd6\xd6\xd6\xd6\xd6\xd6\xd6\xd6\xd6\xd6\xd6\xd6\xd6\xd6\xd6\xd6\xd6\xd6\xd6\xd6\xd6\xd6\xd6\xd6\xd6\xdc' +'!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!' +'!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!' +'!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!' +'!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!' +'!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!' +'!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!' +'!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f' +'\xda\xda\xda\xda\xda\xda\xda\xda\xda\xda\xda\xda\xda\xda\xda\xda\xda\xda\xda\xda\xda\xda\xda\xda\xda\xda\xda\xda\xda\xda\xda\xda\xda\xda\xda\xda\xda\xda\xda\xda\xda\xda\xda\xda\xda\xda\xda\xda\xda\xda\xda\xda\xda\xda\xda\xda\xda\xda\xda\xda\xda\xda\xda\xda' +'!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!' +'!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!' +'!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!\x0f\x0f\x0f\x0f' +'\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f' +'!!!!!!!!!!!!!!!!!!!!!\x1b!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!' +'!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!' +'!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!' +'!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!' +'!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!' +'!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!' +'!!!!!!!!!!!!!\x0f\x0f\x0f\xdc\xdc\xdc\xdc\xdc\xdc\xdc\xdc\xdc\xdc\xdc\xdc\xdc\xdc\xdc\xdc\xdc\xdc\xdc\xdc\xdc\xdc\xdc\xdc\xdc\xdc\xdc\xdc\xdc\xdc\xdc\xdc\xdc\xdc\xdc\xdc\xdc\xdc\xdc\xdc\xdc\xdc\xdc\xdc\xdc\xdc\xdc\xdc' +'\xdc\xdc\xdc\xdc\xdc\xdc\xdc\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f' +'\xbc\xbc\xbc\xbc\xbc\xbc\xbc\xbc\xbc\xbc\xbc\xbc\xbc\xbc\xbc\xbc\xbc\xbc\xbc\xbc\xbc\xbc\xbc\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f' +'\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f' +'\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f' +'\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f' +' + ; 8 ((88(\xda\xda\xda\xda\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f' +'\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f' +'\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f' +'\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f' +'!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!' +'!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!' +'!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f' +'\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f' +'\x12\x12\x12\x12\x12\x12\x12\x12\x12\x12\x12\x12\x12\x12\x12\x12\x12\x12\x12\x12\x12\x12\x12\x12\x12\x12\x12\x12\x12\x12\x12\x12\x12\x12\x12\x12\x12\x12\x12\x12\x12\x12\x12\x12\x12\x12\x12\x12\x12\x12\x12\x12\x12\x12\x12\x12\x12\x12\x12\x12\x12\x12\x12\x12' +'\x12\x12\x12\x12\x12\x12\x12\x12\x12\x12\x12\x12\x12\x12\x12\x12\x12\x12\x12\x12\x12\x12\x12\x12\x12\x12\x12\x12\x12\x12\x12\x12\x12\x12\x12\x12\x12\x12\x12\x12\x12\x12\x12\x12\x12\x12\x12\x12\x12\x12\x12\x12\x12\x12\x12\x12\x12\x12\x12\x12\x12\x12\x12\x12' +'\x12\x12\x12\x12\x12\x12\x12\x12\x12\x12\x12\x12\x12\x12\x12\x12\x12\x12\x12\x12\x12\x12\x12\x12\x12\x12\x12\x12\x12\x12\x12\x12\x12\x12\x12\x12\x12\x12\x12\x12\x12\x12\x12\x12\x12\x12\x12\x12\x12\x12\x12\x12\x12\x12\x12\x12\x12\x12\x12\x12\x12\x12\x12\x12' +'\x12\x12\x12\x12\x12\x12\x12\x12\x12\x12\x12\x12\x12\x12\x12\x12\x12\x12\x12\x12\x12\x12\x12\x12\x12\x12\x12\x12\x12\x12\x12\x12\x12\x12\x12\x12\x12\x12\x12\x12\x12\x12\x12\x12\x12\x12\x12\x12\x12\x12\x12\x12\x12\x12\x12\x12\x12\x12\x12\x12\x12\x12\x12\x12' +'\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11' +'\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11' +'\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11' +'\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11' +'!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!\x0f\x0f!!!!!!!!!!!!!!!!' +'!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!\x0f\x0f\x0f\x0f\x0f!!!!!!!!!!!!!!!!' +'!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!' +'!!!!!!!!!!!!!!!!!!!!!!!!!!\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f' +'\x15\x15\x15\x15\x15\x15\x15\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x15\x15\x15\x15\x15\x0f\x0f\x0f\x0f\x0f"L""""""""""\xc1"""""""""""""\x0f"""""\x0f"\x0f' +'""\x0f""\x0f""""""""""\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e' +'\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f' +'\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e' +'\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e' +'\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e' +'\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e' +'\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e' +'\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e\xae\x8f' +'\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e' +'\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x0f\x0f\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e' +'\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e\xb3\xda\x0f\x0f' +'................\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xb1\x92\xaa\x0f\x0f\x0f\x0f\x0f\x0fdddd\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\xaa\x8c\x8c\x86\x86\xb1\x92\xb1\x92\xb1\x92\xb1\x92\xb1\x92\xb1' +'\x92\xb1\x92\xb1\x92\xaa\xaa\xb1\x92\xaa\xaa\xaa\xaa\x86\x86\x86\x9e\xaa\x9e\x0f\xaa\x9e\xaa\xaa\x8c\xb1\x92\xb1\x92\xb1\x92\xa3\xaa\xaa\xc3\x89\xd0\xd0\xd0\x0f\xaa\xb9\xa3\xaa\x0f\x0f\x0f\x0f\x1e\x1e\x1e\x1e\x1e\x0f\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e' +'\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e' +'\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x1e\x0f\x0f\x06' +'\x0f\xa6\xa6\xa0\xb5\xa0\xa6\xa6\xac\x8d\xa6\xc0\x9b\x87\x9b\x9bllllllllll\x9b\xa6\xca\xc9\xca\xa6\xa6%%%%%%%%%%%%%%%%%%%%%%%%%%\xac\xa6\x8d\xbb\x83' +'\xbb\x14\x14\x14\x14\x14\x14\x14\x14\x14\x14\x14\x14\x14\x14\x14\x14\x14\x14\x14\x14\x14\x14\x14\x14\x14\x14\xac\xc9\x8d\xc9\xac\x8d\xa7\xad\x8e\xa7\xa7\x1f\x1f\x1f\x1f\x1f\x1f\x1f\x1f\x1f\x1f\x19\x1f\x1f\x1f\x1f\x1f\x1f\x1f\x1f\x1f\x1f\x1f\x1f\x1f\x1f\x1f' +'\x1f\x1f\x1f\x1f\x1f\x1f\x1f\x1f\x1f\x1f\x1f\x1f\x1f\x1f\x1f\x1f\x1f\x1f\x1f\x1f\x1f\x1f\x1f\x1f\x1f\x1f\x1f\x1f\x1f\x1f\x19\x19\x1f\x1f\x1f\x1f\x1f\x1f\x1f\x1f\x1f\x1f\x1f\x1f\x1f\x1f\x1f\x1f\x1f\x1f\x1f\x1f\x1f\x1f\x1f\x1f\x1f\x1f\x1f\x1f\x1f\x1f\x1f\x0f' +'\x0f\x0f\x1f\x1f\x1f\x1f\x1f\x1f\x0f\x0f\x1f\x1f\x1f\x1f\x1f\x1f\x0f\x0f\x1f\x1f\x1f\x1f\x1f\x1f\x0f\x0f\x1f\x1f\x1f\x0f\x0f\x0f\xb5\xb5\xc9\xbb\xd8\xb5\xb5\x0f\xd9\xcb\xcb\xcb\xcb\xd9\xd9\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\n\n\n\xda\xd7\x0f\x0f' +' \x0f \x0f \x0f \x0f ' +' \x0f\x0f \x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f' +' ' +' \x0f\x0f\x0f\x0f\x0f' +'\xa4\xa8\xd5\x0f\x0f\x0f\x0fyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyy\x0f\x0f\x0f\xd5\xd5\xd5\xd5\xd5\xd5\xd5\xd5\xd5' +'ttttttttttttttttttttttttttttttttttttttttttttttttttttt~~~~\xda\xda\xda\xda\xda\xda\xda' +'\xda\xda\xda\xda\xda\xda\xda\xda\xda\xda~\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f' +'\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f' +' \x0fyyyy\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f ' +' r\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f' +' \x0f\xa4 ' +' \x0f\x0f\x0f\x0f \xd5ttttt\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f' +'&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&\x15\x15\x15\x15\x15\x15\x15\x15\x15\x15\x15\x15\x15\x15\x15\x15\x15\x15\x15\x15\x15\x15\x15\x15' +'\x15\x15\x15\x15\x15\x15\x15\x15\x15\x15\x15\x15\x15\x15\x15\x15 ' +' \x0f\x0foooooooooo\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f' +'\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f' +'""""""\x0f\x0f"\x0f""""""""""""""""""""""""""""""""""""""""""""\x0f""\x0f\x0f\x0f"\x0f\x0f"' '\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f' '\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f' '\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f' +'"888\x0f88\x0f\x0f\x0f\x0f\x0f8a8d""""\x0f"""\x0f"""""""""""""""""""""""""""\x0f\x0f\x0f\x0fd9a\x0f\x0f\x0f\x0f;' +'\x82\x82\x82\x82\x81\x81\x81\x81\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\xab\xab\xab\xab\xab\xab\xab\xab\xab\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f' '\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f' -'\x0e\x0e\x0e\x0e\x0e\x0e\x0e\x0e\x0e\x0e\x0e\x0e\x0e\x0e\x0e\x0e\x0e\x0e\x0e\x0e\x0e\x0e\x0e\x0e\x0e\x0e\x0e\x0e\x0e\x0e\x0e\x0e\x0e\x0e\x0e\x0e\x0e\x0e\x0e\x0e\x0e\x0e\x0e\x0e\x0e\x0e\x0e\x0e\x0e\x0e\x0e\x0e\x0e\x0e\x0e\x0e\x0e\x0e\x0e\x0e\x0e\x0e\x0e\x0e' -'\x0e\x0e\x0e\x0e\x0e\x0e\x0e\x0e\x0e\x0e\x0e\x0e\x0e\x0e\x0e\x0e\x0e\x0e\x0e\x0e\x0e\x0e\x0e\x0e\x0e\x0e\x0e\x0e\x0e\x0e\x0e\x0e\x0e\x0e\x0e\x0e\x0e\x0e\x0e\x0e\x0e\x0e\x0e\x0e\x0e\x0e\x0e\x0e\x0e\x0e\x0e\x0e\x0e\x0e\x0e\x0e\x0e\x0e\x0e\x0e\x0e\x0e\x0e\x0e' -'\x0e\x0e\x0e\x0e\x0e\x0e\x0e\x0e\x0e\x0e\x0e\x0e\x0e\x0e\x0e\x0e\x0e\x0e\x0e\x0e\x0e\x0e\x0e\x0e\x0e\x0e\x0e\x0e\x0e\x0e\x0e\x0e\x0e\x0e\x0e\x0e\x0e\x0e\x0e\x0e\x0e\x0e\x0e\x0e\x0e\x0e\x0e\x0e\x0e\x0e\x0e\x0e\x0e\x0e\x0e\x0e\x0e\x0e\x0e\x0e\x0e\x0e\x0e\x0e' -'\x0e\x0e\x0e\x0e\x0e\x0e\x0e\x0e\x0e\x0e\x0e\x0e\x0e\x0e\x0e\x0e\x0e\x0e\x0e\x0e\x0e\x0e\x0e\x0e\x0e\x0e\x0e\x0e\x0e\x0e\x0e\x0e\x0e\x0e\x0e\x0e\x0e\x0e\x0e\x0e\x0e\x0e\x0e\x0e\x0e\x0e\x0e\x0e\x0e\x0e\x0e\x0e\x0e\x0e\x0e\x0e\x0e\x0e\x0e\x0e\x0e\x0e\x0e\x0e' -'\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\r\r\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c' -'\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r' -'\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r' -'\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r' -'\x12\x12\x12\x12\x12\x12\x12\r\r\r\r\r\r\r\r\r\r\r\r\x12\x12\x12\x12\x12\r\r\r\r\r\x1dE\x1d\x1d\x1d\x1d\x1d\x1d\x1d\x1d\x1d\x1d\xbb\x1d\x1d\x1d\x1d\x1d\x1d\x1d\x1d\x1d\x1d\x1d\x1d\x1d\r\x1d\x1d\x1d\x1d\x1d\r\x1d\r' -'\x1d\x1d\r\x1d\x1d\r\x1d\x1d\x1d\x1d\x1d\x1d\x1d\x1d\x1d\x1d\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19' -'\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\r\r\r\r\r\r\r\r\r\r\r\r\r\r' -'\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19' -'\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19' -'\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19' -'\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19' -'\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19' -'\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\xa8\x87' -'\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19' -'\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\r\r\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19' -'\x19\x19\x19\x19\x19\x19\x19\x19\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\xad\r\r\r' -"''''''''''''''''\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r]]]]\r\r\r\r\r\r\r\r\r\r\r\r\xa4\x84\x84~~\xab\x8a\xab\x8a\xab\x8a\xab\x8a\xab\x8a\xab" -'\x8a\xab\x8a\xab\x8a\xa4\xa4\r\r\xa4\xa4\xa4\xa4~~~\x96\xa4\x96\r\xa4\x96\xa4\xa4\x84\xab\x8a\xab\x8a\xab\x8a\x9d\xa4\xa4\xbd\x81\xc8\xc8\xc8\r\xa4\xb3\x9d\xa4\r\r\r\r\x19\x19\x19\x19\x19\r\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19' -'\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19' -'\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\x19\r\r\x05' -'\r\xa0\xa0\x9a\xaf\x9a\xa0\xa0\xa6\x85\xa0\xba\x93\x7f\x93\x97eeeeeeeeee\x93\xa0\xc2\xc1\xc2\xa0\xa0 \xa6\xa0\x85\xb5z' -'\xb5\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\xa6\xc1\x85\xc1\xa6\x85\xa1\xa7\x86\xa1{\x1a\x1a\x1a\x1a\x1a\x1a\x1a\x1a\x1a\x1a\x16\x1a\x1a\x1a\x1a\x1a\x1a\x1a\x1a\x1a\x1a\x1a\x1a\x1a\x1a\x1a' -'\x1a\x1a\x1a\x1a\x1a\x1a\x1a\x1a\x1a\x1a\x1a\x1a\x1a\x1a\x1a\x1a\x1a\x1a\x1a\x1a\x1a\x1a\x1a\x1a\x1a\x1a\x1a\x1a\x1a\x1a\x16\x16\x1a\x1a\x1a\x1a\x1a\x1a\x1a\x1a\x1a\x1a\x1a\x1a\x1a\x1a\x1a\x1a\x1a\x1a\x1a\x1a\x1a\x1a\x1a\x1a\x1a\x1a\x1a\x1a\x1a\x1a\x1a\r' -'\r\r\x1a\x1a\x1a\x1a\x1a\x1a\r\r\x1a\x1a\x1a\x1a\x1a\x1a\r\r\x1a\x1a\x1a\x1a\x1a\x1a\r\r\x1a\x1a\x1a\r\r\r\xaf\xaf\xc1\xb5\xd0\xaf\xaf\r\xd1\xc3\xc3\xc3\xc3\xd1\xd1\r\r\r\r\r\r\r\r\r\r\x05\x05\x05\xd2\xcf\r\r' -'\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\rssss\r\r\r\r\r\r\r\r\r\r\r\r\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b' -'\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1b\x1bj\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r' -'\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r' -'\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r' -'!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!\r\r\x12\x12\x12\x12\x12\x12\x12\x12\x12\x12\x12\x12\x12\x12\x12\x12\x12\x12\x12\x12\x12\x12\x12\x12' -'\x12\x12\x12\x12\x12\x12\x12\x12\x12\x12\x12\x12\x12\x12\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r' -'\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r' -'\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r' -'\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd' -'\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd' -'\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd' -'\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\r\r\r\r\r\r\r\r\r\r' -'\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\r\r\r\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd' -'\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd$$222\xcd\xcd\xcd%$$$$$\x05\x05\x05\x05\x05\x05\x05\x05ZZZZZ' -'ZZZ\xcd\xcd]]]]]ZZ\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd]]]]\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd' -'\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r' -'!!!!!!!!!!!!!!!!!!!!!!!!!!\x12\x12\x12\x12\x12\x12\x12\x12\x12\x12\x12\x12\x12\x12\x12\x12\x12\x12\x12\x12\x12\x12\x12\x12\x12\x12!!!!!!!!!!!!' -'!!!!!!!!!!!!!!\x12\x12\x12\x12\x12\x12\x12\r\x12\x12\x12\x12\x12\x12\x12\x12\x12\x12\x12\x12\x12\x12\x12\x12\x12\x12!!!!!!!!!!!!!!!!!!!!!!!!' -'!!\x12\x12\x12\x12\x12\x12\x12\x12\x12\x12\x12\x12\x12\x12\x12\x12\x12\x12\x12\x12\x12\x12\x12\x12\x12\x12!\r!!\r\r!\r\r!!\r\r!!!!\r!!!!!!!!\x12\x12\x12\x12\r\x12\r\x12\x12\x12' -'\x12\r\x12\x12\r\x12\x12\x12\x12\x12\x12\x12\x12\x12\x12\x12!!!!!!!!!!!!!!!!!!!!!!!!!!\x12\x12\x12\x12\x12\x12\x12\x12\x12\x12\x12\x12\x12\x12\x12\x12\x12\x12\x12\x12\x12\x12' -'\x12\x12\x12\x12!!\r!!!!\r\r!!!!!!!!\r!!!!!!!\r\x12\x12\x12\x12\x12\x12\x12\x12\x12\x12\x12\x12\x12\x12\x12\x12\x12\x12\x12\x12\x12\x12\x12\x12\x12\x12!!\r!!!!\r' -'!!!!!\r!\r\r\r!!!!!!!\r\x12\x12\x12\x12\x12\x12\x12\x12\x12\x12\x12\x12\x12\x12\x12\x12\x12\x12\x12\x12\x12\x12\x12\x12\x12\x12!!!!!!!!!!!!!!!!!!!!' -'!!!!!!\x12\x12\x12\x12\x12\x12\x12\x12\x12\x12\x12\x12\x12\x12\x12\x12\x12\x12\x12\x12\x12\x12\x12\x12\x12\x12!!!!!!!!!!!!!!!!!!!!!!!!!!\x12\x12\x12\x12\x12\x12' -'\x12\x12\x12\x12\x12\x12\x12\x12\x12\x12\x12\x12\x12\x12\x12\x12\x12\x12\x12\x12!!!!!!!!!!!!!!!!!!!!!!!!!!\x12\x12\x12\x12\x12\x12\x12\x12\x12\x12\x12\x12\x12\x12\x12\x12\x12\x12' -'\x12\x12\x12\x12\x12\x12\x12\x12!!!!!!!!!!!!!!!!!!!!!!!!!!\x12\x12\x12\x12\x12\x12\x12\x12\x12\x12\x12\x12\x12\x12\x12\x12\x12\x12\x12\x12\x12\x12\x12\x12\x12\x12!!!!' -'!!!!!!!!!!!!!!!!!!!!!!\x12\x12\x12\x12\x12\x12\x12\x12\x12\x12\x12\x12\x12\x12\x12\x12\x12\x12\x12\x12\x12\x12\x12\x12\x12\x12!!!!!!!!!!!!!!!!' -'!!!!!!!!!!\x12\x12\x12\x12\x12\x12\x12\x12\x12\x12\x12\x12\x12\x12\x12\x12\x12\x12\x12\x12\x12\x12\x12\x12\x12\x12\r\r\r\r!!!!!!!!!!!!!!!!!!!!!!!!' -'!\xbe\x12\x12\x12\x12\x12\x12\x12\x12\x12\x12\x12\x12\x12\x12\x12\x12\x12\x12\x12\x12\x12\x12\x12\x12\x12\xbe\x12\x12\x12\x12\x12\x12!!!!!!!!!!!!!!!!!!!!!!!!!\xbe\x12\x12\x12\x12' -'\x12\x12\x12\x12\x12\x12\x12\x12\x12\x12\x12\x12\x12\x12\x12\x12\x12\x12\x12\x12\x12\xbe\x12\x12\x12\x12\x12\x12!!!!!!!!!!!!!!!!!!!!!!!!!\xbe\x12\x12\x12\x12\x12\x12\x12\x12\x12\x12' -'\x12\x12\x12\x12\x12\x12\x12\x12\x12\x12\x12\x12\x12\x12\x12\xbe\x12\x12\x12\x12\x12\x12!!!!!!!!!!!!!!!!!!!!!!!!!\xbe\x12\x12\x12\x12\x12\x12\x12\x12\x12\x12\x12\x12\x12\x12\x12\x12' -'\x12\x12\x12\x12\x12\x12\x12\x12\x12\xbe\x12\x12\x12\x12\x12\x12!!!!!!!!!!!!!!!!!!!!!!!!!\xbe\x12\x12\x12\x12\x12\x12\x12\x12\x12\x12\x12\x12\x12\x12\x12\x12\x12\x12\x12\x12\x12\x12' -'\x12\x12\x12\xbe\x12\x12\x12\x12\x12\x12\r\r\r\rffffffffffffffffffffffffffffffffffffffffffffffffff' -'\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c' -'\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c' -'\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c' -'\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r' -'\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\x1c\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r' -'\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r' -'\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r' -'\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r' -'\r\x05\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\x05\x05\x05\x05\x05\x05\x05\x05\x05\x05\x05\x05\x05\x05\x05\x05\x05\x05\x05\x05\x05\x05\x05\x05\x05\x05\x05\x05\x05\x05\x05\x05' -'\x05\x05\x05\x05\x05\x05\x05\x05\x05\x05\x05\x05\x05\x05\x05\x05\x05\x05\x05\x05\x05\x05\x05\x05\x05\x05\x05\x05\x05\x05\x05\x05\x05\x05\x05\x05\x05\x05\x05\x05\x05\x05\x05\x05\x05\x05\x05\x05\x05\x05\x05\x05\x05\x05\x05\x05\x05\x05\x05\x05\x05\x05\x05\x05' -'\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r' -'\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r\r' -'\x0e\x0e\x0e\x0e\x0e\x0e\x0e\x0e\x0e\x0e\x0e\x0e\x0e\x0e\x0e\x0e\x0e\x0e\x0e\x0e\x0e\x0e\x0e\x0e\x0e\x0e\x0e\x0e\x0e\x0e\x0e\x0e\x0e\x0e\x0e\x0e\x0e\x0e\x0e\x0e\x0e\x0e\x0e\x0e\x0e\x0e\x0e\x0e\x0e\x0e\x0e\x0e\x0e\x0e\x0e\x0e\x0e\x0e\x0e\x0e\x0e\x0e\x0e\x0e' -'\x0e\x0e\x0e\x0e\x0e\x0e\x0e\x0e\x0e\x0e\x0e\x0e\x0e\x0e\x0e\x0e\x0e\x0e\x0e\x0e\x0e\x0e\x0e\x0e\x0e\x0e\x0e\x0e\x0e\x0e\x0e\x0e\x0e\x0e\x0e\x0e\x0e\x0e\x0e\x0e\x0e\x0e\x0e\x0e\x0e\x0e\x0e\x0e\x0e\x0e\x0e\x0e\x0e\x0e\x0e\x0e\x0e\x0e\x0e\x0e\x0e\x0e\x0e\x0e' -'\x0e\x0e\x0e\x0e\x0e\x0e\x0e\x0e\x0e\x0e\x0e\x0e\x0e\x0e\x0e\x0e\x0e\x0e\x0e\x0e\x0e\x0e\x0e\x0e\x0e\x0e\x0e\x0e\x0e\x0e\x0e\x0e\x0e\x0e\x0e\x0e\x0e\x0e\x0e\x0e\x0e\x0e\x0e\x0e\x0e\x0e\x0e\x0e\x0e\x0e\x0e\x0e\x0e\x0e\x0e\x0e\x0e\x0e\x0e\x0e\x0e\x0e\x0e\x0e' -'\x0e\x0e\x0e\x0e\x0e\x0e\x0e\x0e\x0e\x0e\x0e\x0e\x0e\x0e\x0e\x0e\x0e\x0e\x0e\x0e\x0e\x0e\x0e\x0e\x0e\x0e\x0e\x0e\x0e\x0e\x0e\x0e\x0e\x0e\x0e\x0e\x0e\x0e\x0e\x0e\x0e\x0e\x0e\x0e\x0e\x0e\x0e\x0e\x0e\x0e\x0e\x0e\x0e\x0e\x0e\x0e\x0e\x0e\x0e\x0e\x0e\x0e\r\r' +'\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f' +'\xd5\xd5\xd5\xd5\xd5\xd5\xd5\xd5\xd5\xd5\xd5\xd5\xd5\xd5\xd5\xd5\xd5\xd5\xd5\xd5\xd5\xd5\xd5\xd5\xd5\xd5\xd5\xd5\xd5\xd5\xd5\xd5\xd5\xd5\xd5\xd5\xd5\xd5\xd5\xd5\xd5\xd5\xd5\xd5\xd5\xd5\xd5\xd5\xd5\xd5\xd5\xd5\xd5\xd5\xd5\xd5\xd5\xd5\xd5\xd5\xd5\xd5\xd5\xd5' +'\xd5\xd5\xd5\xd5\xd5\xd5\xd5\xd5\xd5\xd5\xd5\xd5\xd5\xd5\xd5\xd5\xd5\xd5\xd5\xd5\xd5\xd5\xd5\xd5\xd5\xd5\xd5\xd5\xd5\xd5\xd5\xd5\xd5\xd5\xd5\xd5\xd5\xd5\xd5\xd5\xd5\xd5\xd5\xd5\xd5\xd5\xd5\xd5\xd5\xd5\xd5\xd5\xd5\xd5\xd5\xd5\xd5\xd5\xd5\xd5\xd5\xd5\xd5\xd5' +'\xd5\xd5\xd5\xd5\xd5\xd5\xd5\xd5\xd5\xd5\xd5\xd5\xd5\xd5\xd5\xd5\xd5\xd5\xd5\xd5\xd5\xd5\xd5\xd5\xd5\xd5\xd5\xd5\xd5\xd5\xd5\xd5\xd5\xd5\xd5\xd5\xd5\xd5\xd5\xd5\xd5\xd5\xd5\xd5\xd5\xd5\xd5\xd5\xd5\xd5\xd5\xd5\xd5\xd5\xd5\xd5\xd5\xd5\xd5\xd5\xd5\xd5\xd5\xd5' +'\xd5\xd5\xd5\xd5\xd5\xd5\xd5\xd5\xd5\xd5\xd5\xd5\xd5\xd5\xd5\xd5\xd5\xd5\xd5\xd5\xd5\xd5\xd5\xd5\xd5\xd5\xd5\xd5\xd5\xd5\xd5\xd5\xd5\xd5\xd5\xd5\xd5\xd5\xd5\xd5\xd5\xd5\xd5\xd5\xd5\xd5\xd5\xd5\xd5\xd5\xd5\xd5\xd5\xd5\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f' +'\xd5\xd5\xd5\xd5\xd5\xd5\xd5\xd5\xd5\xd5\xd5\xd5\xd5\xd5\xd5\xd5\xd5\xd5\xd5\xd5\xd5\xd5\xd5\xd5\xd5\xd5\xd5\xd5\xd5\xd5\xd5\xd5\xd5\xd5\xd5\xd5\xd5\xd5\xd5\x0f\x0f\x0f\xd5\xd5\xd5\xd5\xd5\xd5\xd5\xd5\xd5\xd5\xd5\xd5\xd5\xd5\xd5\xd5\xd5\xd5\xd5\xd5\xd5\xd5' +'\xd5\xd5\xd5\xd5\xd5\xd5\xd5\xd5\xd5\xd5\xd5\xd5\xd5\xd5\xd5\xd5\xd5\xd5\xd5\xd5\xd5\xd5\xd5\xd5\xd5\xd5\xd5\xd5\xd5\xd5\xd5\xd5\xd5\xd5\xd5\xd5\xd5))999\xd5\xd5\xd5*)))))\x06\x06\x06\x06\x06\x06\x06\x06aaaaa' +'aaa\xd5\xd5dddddaa\xd5\xd5\xd5\xd5\xd5\xd5\xd5\xd5\xd5\xd5\xd5\xd5\xd5\xd5\xd5\xd5\xd5\xd5\xd5\xd5\xd5\xd5\xd5\xd5\xd5\xd5\xd5\xd5\xd5\xd5dddd\xd5\xd5\xd5\xd5\xd5\xd5\xd5\xd5\xd5\xd5\xd5\xd5\xd5\xd5\xd5\xd5\xd5\xd5' +'\xd5\xd5\xd5\xd5\xd5\xd5\xd5\xd5\xd5\xd5\xd5\xd5\xd5\xd5\xd5\xd5\xd5\xd5\xd5\xd5\xd5\xd5\xd5\xd5\xd5\xd5\xd5\xd5\xd5\xd5\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f' +'\xda\xda\xda\xda\xda\xda\xda\xda\xda\xda\xda\xda\xda\xda\xda\xda\xda\xda\xda\xda\xda\xda\xda\xda\xda\xda\xda\xda\xda\xda\xda\xda\xda\xda\xda\xda\xda\xda\xda\xda\xda\xda\xda\xda\xda\xda\xda\xda\xda\xda\xda\xda\xda\xda\xda\xda\xda\xda\xda\xda\xda\xda\xda\xda' +'\xda\xdaddd\xda\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f' +'\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f' +'\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f' +'\xda\xda\xda\xda\xda\xda\xda\xda\xda\xda\xda\xda\xda\xda\xda\xda\xda\xda\xda\xda\xda\xda\xda\xda\xda\xda\xda\xda\xda\xda\xda\xda\xda\xda\xda\xda\xda\xda\xda\xda\xda\xda\xda\xda\xda\xda\xda\xda\xda\xda\xda\xda\xda\xda\xda\xda\xda\xda\xda\xda\xda\xda\xda\xda' +'\xda\xda\xda\xda\xda\xda\xda\xda\xda\xda\xda\xda\xda\xda\xda\xda\xda\xda\xda\xda\xda\xda\xda\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f' +'\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f' +'\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f' +'&&&&&&&&&&&&&&&&&&&&&&&&&&\x15\x15\x15\x15\x15\x15\x15\x15\x15\x15\x15\x15\x15\x15\x15\x15\x15\x15\x15\x15\x15\x15\x15\x15\x15\x15&&&&&&&&&&&&' +'&&&&&&&&&&&&&&\x15\x15\x15\x15\x15\x15\x15\x0f\x15\x15\x15\x15\x15\x15\x15\x15\x15\x15\x15\x15\x15\x15\x15\x15\x15\x15&&&&&&&&&&&&&&&&&&&&&&&&' +'&&\x15\x15\x15\x15\x15\x15\x15\x15\x15\x15\x15\x15\x15\x15\x15\x15\x15\x15\x15\x15\x15\x15\x15\x15\x15\x15&\x0f&&\x0f\x0f&\x0f\x0f&&\x0f\x0f&&&&\x0f&&&&&&&&\x15\x15\x15\x15\x0f\x15\x0f\x15\x15\x15' +'\x15\x15\x15\x15\x0f\x15\x15\x15\x15\x15\x15\x15\x15\x15\x15\x15&&&&&&&&&&&&&&&&&&&&&&&&&&\x15\x15\x15\x15\x15\x15\x15\x15\x15\x15\x15\x15\x15\x15\x15\x15\x15\x15\x15\x15\x15\x15' +'\x15\x15\x15\x15&&\x0f&&&&\x0f\x0f&&&&&&&&\x0f&&&&&&&\x0f\x15\x15\x15\x15\x15\x15\x15\x15\x15\x15\x15\x15\x15\x15\x15\x15\x15\x15\x15\x15\x15\x15\x15\x15\x15\x15&&\x0f&&&&\x0f' +'&&&&&\x0f&\x0f\x0f\x0f&&&&&&&\x0f\x15\x15\x15\x15\x15\x15\x15\x15\x15\x15\x15\x15\x15\x15\x15\x15\x15\x15\x15\x15\x15\x15\x15\x15\x15\x15&&&&&&&&&&&&&&&&&&&&' +'&&&&&&\x15\x15\x15\x15\x15\x15\x15\x15\x15\x15\x15\x15\x15\x15\x15\x15\x15\x15\x15\x15\x15\x15\x15\x15\x15\x15&&&&&&&&&&&&&&&&&&&&&&&&&&\x15\x15\x15\x15\x15\x15' +'\x15\x15\x15\x15\x15\x15\x15\x15\x15\x15\x15\x15\x15\x15\x15\x15\x15\x15\x15\x15&&&&&&&&&&&&&&&&&&&&&&&&&&\x15\x15\x15\x15\x15\x15\x15\x15\x15\x15\x15\x15\x15\x15\x15\x15\x15\x15' +'\x15\x15\x15\x15\x15\x15\x15\x15&&&&&&&&&&&&&&&&&&&&&&&&&&\x15\x15\x15\x15\x15\x15\x15\x15\x15\x15\x15\x15\x15\x15\x15\x15\x15\x15\x15\x15\x15\x15\x15\x15\x15\x15&&&&' +'&&&&&&&&&&&&&&&&&&&&&&\x15\x15\x15\x15\x15\x15\x15\x15\x15\x15\x15\x15\x15\x15\x15\x15\x15\x15\x15\x15\x15\x15\x15\x15\x15\x15&&&&&&&&&&&&&&&&' +'&&&&&&&&&&\x15\x15\x15\x15\x15\x15\x15\x15\x15\x15\x15\x15\x15\x15\x15\x15\x15\x15\x15\x15\x15\x15\x15\x15\x15\x15\x15\x15\x0f\x0f&&&&&&&&&&&&&&&&&&&&&&&&' +'&\xc6\x15\x15\x15\x15\x15\x15\x15\x15\x15\x15\x15\x15\x15\x15\x15\x15\x15\x15\x15\x15\x15\x15\x15\x15\x15\xc6\x15\x15\x15\x15\x15\x15&&&&&&&&&&&&&&&&&&&&&&&&&\xc6\x15\x15\x15\x15' +'\x15\x15\x15\x15\x15\x15\x15\x15\x15\x15\x15\x15\x15\x15\x15\x15\x15\x15\x15\x15\x15\xc6\x15\x15\x15\x15\x15\x15&&&&&&&&&&&&&&&&&&&&&&&&&\xc6\x15\x15\x15\x15\x15\x15\x15\x15\x15\x15' +'\x15\x15\x15\x15\x15\x15\x15\x15\x15\x15\x15\x15\x15\x15\x15\xc6\x15\x15\x15\x15\x15\x15&&&&&&&&&&&&&&&&&&&&&&&&&\xc6\x15\x15\x15\x15\x15\x15\x15\x15\x15\x15\x15\x15\x15\x15\x15\x15' +'\x15\x15\x15\x15\x15\x15\x15\x15\x15\xc6\x15\x15\x15\x15\x15\x15&&&&&&&&&&&&&&&&&&&&&&&&&\xc6\x15\x15\x15\x15\x15\x15\x15\x15\x15\x15\x15\x15\x15\x15\x15\x15\x15\x15\x15\x15\x15\x15' +'\x15\x15\x15\xc6\x15\x15\x15\x15\x15\x15\x0f\x0f\x0f\x0fmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmm' +'!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!' +'!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!' +'!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!' +'!!!!!!!!!!!!!!!!!!!!!!!\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\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\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\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\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\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\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\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\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' +'!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!\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\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\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\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\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\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\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\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\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\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\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\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\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\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\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x10\x0f\x0f' +'\x0f\x06\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x06\x06\x06\x06\x06\x06\x06\x06\x06\x06\x06\x06\x06\x06\x06\x06\x06\x06\x06\x06\x06\x06\x06\x06\x06\x06\x06\x06\x06\x06\x06\x06' +'\x06\x06\x06\x06\x06\x06\x06\x06\x06\x06\x06\x06\x06\x06\x06\x06\x06\x06\x06\x06\x06\x06\x06\x06\x06\x06\x06\x06\x06\x06\x06\x06\x06\x06\x06\x06\x06\x06\x06\x06\x06\x06\x06\x06\x06\x06\x06\x06\x06\x06\x06\x06\x06\x06\x06\x06\x06\x06\x06\x06\x06\x06\x06\x06' +'\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f' +'\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f' +'................................................................' +'................................................................' +'................................................................' +'................................................\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f\x0f' +'\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11' +'\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11' +'\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11' +'\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x0f\x0f' ) def _get_record(code): @@ -14480,9 +17036,6 @@ 55: 7, 56: 8, 57: 9, -178: 2, -179: 3, -185: 1, 1632: 0, 1633: 1, 1634: 2, @@ -14553,6 +17106,7 @@ 2925: 7, 2926: 8, 2927: 9, +3046: 0, 3047: 1, 3048: 2, 3049: 3, @@ -14632,15 +17186,6 @@ 4167: 7, 4168: 8, 4169: 9, -4969: 1, -4970: 2, -4971: 3, -4972: 4, -4973: 5, -4974: 6, -4975: 7, -4976: 8, -4977: 9, 6112: 0, 6113: 1, 6114: 2, @@ -14661,23 +17206,26 @@ 6167: 7, 6168: 8, 6169: 9, -8304: 0, -8308: 4, -8309: 5, -8310: 6, -8311: 7, -8312: 8, -8313: 9, -8320: 0, -8321: 1, -8322: 2, -8323: 3, -8324: 4, -8325: 5, -8326: 6, -8327: 7, -8328: 8, -8329: 9, +6470: 0, +6471: 1, +6472: 2, +6473: 3, +6474: 4, +6475: 5, +6476: 6, +6477: 7, +6478: 8, +6479: 9, +6608: 0, +6609: 1, +6610: 2, +6611: 3, +6612: 4, +6613: 5, +6614: 6, +6615: 7, +6616: 8, +6617: 9, 65296: 0, 65297: 1, 65298: 2, @@ -14688,6 +17236,16 @@ 65303: 7, 65304: 8, 65305: 9, +66720: 0, +66721: 1, +66722: 2, +66723: 3, +66724: 4, +66725: 5, +66726: 6, +66727: 7, +66728: 8, +66729: 9, 120782: 0, 120783: 1, 120784: 2, @@ -14824,6 +17382,7 @@ 2925: 7, 2926: 8, 2927: 9, +3046: 0, 3047: 1, 3048: 2, 3049: 3, @@ -14932,6 +17491,26 @@ 6167: 7, 6168: 8, 6169: 9, +6470: 0, +6471: 1, +6472: 2, +6473: 3, +6474: 4, +6475: 5, +6476: 6, +6477: 7, +6478: 8, +6479: 9, +6608: 0, +6609: 1, +6610: 2, +6611: 3, +6612: 4, +6613: 5, +6614: 6, +6615: 7, +6616: 8, +6617: 9, 8304: 0, 8308: 4, 8309: 5, @@ -14986,6 +17565,7 @@ 9467: 7, 9468: 8, 9469: 9, +9471: 0, 10102: 1, 10103: 2, 10104: 3, @@ -15023,6 +17603,20 @@ 65303: 7, 65304: 8, 65305: 9, +66720: 0, +66721: 1, +66722: 2, +66723: 3, +66724: 4, +66725: 5, +66726: 6, +66727: 7, +66728: 8, +66729: 9, +68160: 1, +68161: 2, +68162: 3, +68163: 4, 120782: 0, 120783: 1, 120784: 2, @@ -15089,9 +17683,9 @@ 178: 2.0, 179: 3.0, 185: 1.0, -188: 0.25, -189: 0.5, -190: 0.75, +188: 1.0 / 4.0, +189: 1.0 / 2.0, +190: 3.0 / 4.0, 1632: 0.0, 1633: 1.0, 1634: 2.0, @@ -15167,6 +17761,7 @@ 2925: 7.0, 2926: 8.0, 2927: 9.0, +3046: 0.0, 3047: 1.0, 3048: 2.0, 3049: 3.0, @@ -15239,16 +17834,16 @@ 3879: 7.0, 3880: 8.0, 3881: 9.0, -3882: 0.5, -3883: 1.5, -3884: 2.5, -3885: 3.5, -3886: 4.5, -3887: 5.5, -3888: 6.5, -3889: 7.5, -3890: 8.5, -3891: -0.5, +3882: 1.0 / 2.0, +3883: 3.0 / 2.0, +3884: 5.0 / 2.0, +3885: 7.0 / 2.0, +3886: 9.0 / 2.0, +3887: 11.0 / 2.0, +3888: 13.0 / 2.0, +3889: 15.0 / 2.0, +3890: 17.0 / 2.0, +3891: -1.0 / 2.0, 4160: 0.0, 4161: 1.0, 4162: 2.0, @@ -15292,6 +17887,16 @@ 6119: 7.0, 6120: 8.0, 6121: 9.0, +6128: 0.0, +6129: 1.0, +6130: 2.0, +6131: 3.0, +6132: 4.0, +6133: 5.0, +6134: 6.0, +6135: 7.0, +6136: 8.0, +6137: 9.0, 6160: 0.0, 6161: 1.0, 6162: 2.0, @@ -15302,6 +17907,26 @@ 6167: 7.0, 6168: 8.0, 6169: 9.0, +6470: 0.0, +6471: 1.0, +6472: 2.0, +6473: 3.0, +6474: 4.0, +6475: 5.0, +6476: 6.0, +6477: 7.0, +6478: 8.0, +6479: 9.0, +6608: 0.0, +6609: 1.0, +6610: 2.0, +6611: 3.0, +6612: 4.0, +6613: 5.0, +6614: 6.0, +6615: 7.0, +6616: 8.0, +6617: 9.0, 8304: 0.0, 8308: 4.0, 8309: 5.0, @@ -15319,18 +17944,18 @@ 8327: 7.0, 8328: 8.0, 8329: 9.0, -8531: 0.33333333333333331, -8532: 0.66666666666666663, -8533: 0.20000000000000001, -8534: 0.40000000000000002, -8535: 0.59999999999999998, -8536: 0.80000000000000004, -8537: 0.16666666666666666, -8538: 0.83333333333333337, -8539: 0.125, -8540: 0.375, -8541: 0.625, -8542: 0.875, +8531: 1.0 / 3.0, +8532: 2.0 / 3.0, +8533: 1.0 / 5.0, +8534: 2.0 / 5.0, +8535: 3.0 / 5.0, +8536: 4.0 / 5.0, +8537: 1.0 / 6.0, +8538: 5.0 / 6.0, +8539: 1.0 / 8.0, +8540: 3.0 / 8.0, +8541: 5.0 / 8.0, +8542: 7.0 / 8.0, 8543: 1.0, 8544: 1.0, 8545: 2.0, @@ -15448,6 +18073,7 @@ 9468: 8.0, 9469: 9.0, 9470: 10.0, +9471: 0.0, 10102: 1.0, 10103: 2.0, 10104: 3.0, @@ -15478,6 +18104,7 @@ 10129: 8.0, 10130: 9.0, 10131: 10.0, +11517: 1.0 / 2.0, 12295: 0.0, 12321: 1.0, 12322: 2.0, @@ -15555,10 +18182,137 @@ 65303: 7.0, 65304: 8.0, 65305: 9.0, +65799: 1.0, +65800: 2.0, +65801: 3.0, +65802: 4.0, +65803: 5.0, +65804: 6.0, +65805: 7.0, +65806: 8.0, +65807: 9.0, +65808: 10.0, +65809: 20.0, +65810: 30.0, +65811: 40.0, +65812: 50.0, +65813: 60.0, +65814: 70.0, +65815: 80.0, +65816: 90.0, +65817: 100.0, +65818: 200.0, +65819: 300.0, +65820: 400.0, +65821: 500.0, +65822: 600.0, +65823: 700.0, +65824: 800.0, +65825: 900.0, +65826: 1000.0, +65827: 2000.0, +65828: 3000.0, +65829: 4000.0, +65830: 5000.0, +65831: 6000.0, +65832: 7000.0, +65833: 8000.0, +65834: 9000.0, +65835: 10000.0, +65836: 20000.0, +65837: 30000.0, +65838: 40000.0, +65839: 50000.0, +65840: 60000.0, +65841: 70000.0, +65842: 80000.0, +65843: 90000.0, +65856: 1.0 / 4.0, +65857: 1.0 / 2.0, +65858: 1.0, +65859: 5.0, +65860: 50.0, +65861: 500.0, +65862: 5000.0, +65863: 50000.0, +65864: 5.0, +65865: 10.0, +65866: 50.0, +65867: 100.0, +65868: 500.0, +65869: 1000.0, +65870: 5000.0, +65871: 5.0, +65872: 10.0, +65873: 50.0, +65874: 100.0, +65875: 500.0, +65876: 1000.0, +65877: 10000.0, +65878: 50000.0, +65879: 10.0, +65880: 1.0, +65881: 1.0, +65882: 1.0, +65883: 2.0, +65884: 2.0, +65885: 2.0, +65886: 2.0, +65887: 5.0, +65888: 10.0, +65889: 10.0, +65890: 10.0, +65891: 10.0, +65892: 10.0, +65893: 30.0, +65894: 50.0, +65895: 50.0, +65896: 50.0, +65897: 50.0, +65898: 100.0, +65899: 300.0, +65900: 500.0, +65901: 500.0, +65902: 500.0, +65903: 500.0, +65904: 500.0, +65905: 1000.0, +65906: 5000.0, +65907: 5.0, +65908: 50.0, +65909: 1.0 / 2.0, +65910: 1.0 / 2.0, +65911: 2.0 / 3.0, +65912: 3.0 / 4.0, +65930: 0.0, 66336: 1.0, 66337: 5.0, 66338: 10.0, 66339: 50.0, +66378: 900.0, +66513: 1.0, +66514: 2.0, +66515: 10.0, +66516: 20.0, +66517: 100.0, +66720: 0.0, +66721: 1.0, +66722: 2.0, +66723: 3.0, +66724: 4.0, +66725: 5.0, +66726: 6.0, +66727: 7.0, +66728: 8.0, +66729: 9.0, +68160: 1.0, +68161: 2.0, +68162: 3.0, +68163: 4.0, +68164: 10.0, +68165: 20.0, +68166: 100.0, +68167: 1000.0, 120782: 0.0, 120783: 1.0, 120784: 2.0, @@ -15750,6 +18504,7 @@ 402: 401, 405: 502, 409: 408, +410: 573, 414: 544, 417: 416, 419: 418, @@ -15818,6 +18573,7 @@ 559: 558, 561: 560, 563: 562, +572: 571, 595: 385, 596: 390, 598: 393, @@ -15837,6 +18593,7 @@ 650: 433, 651: 434, 658: 439, +660: 577, 837: 921, 940: 902, 941: 904, @@ -15890,8 +18647,10 @@ 1007: 1006, 1008: 922, 1009: 929, -1010: 931, +1010: 1017, 1013: 917, +1016: 1015, +1019: 1018, 1072: 1040, 1073: 1041, 1074: 1042, @@ -16010,6 +18769,7 @@ 1265: 1264, 1267: 1266, 1269: 1268, +1271: 1270, 1273: 1272, 1281: 1280, 1283: 1282, @@ -16317,6 +19077,141 @@ 9447: 9421, 9448: 9422, 9449: 9423, +11312: 11264, +11313: 11265, +11314: 11266, +11315: 11267, +11316: 11268, +11317: 11269, +11318: 11270, +11319: 11271, +11320: 11272, +11321: 11273, +11322: 11274, +11323: 11275, +11324: 11276, +11325: 11277, +11326: 11278, +11327: 11279, +11328: 11280, +11329: 11281, +11330: 11282, +11331: 11283, +11332: 11284, +11333: 11285, +11334: 11286, +11335: 11287, +11336: 11288, +11337: 11289, +11338: 11290, +11339: 11291, +11340: 11292, +11341: 11293, +11342: 11294, +11343: 11295, +11344: 11296, +11345: 11297, +11346: 11298, +11347: 11299, +11348: 11300, +11349: 11301, +11350: 11302, +11351: 11303, +11352: 11304, +11353: 11305, +11354: 11306, +11355: 11307, +11356: 11308, +11357: 11309, +11358: 11310, +11393: 11392, +11395: 11394, +11397: 11396, +11399: 11398, +11401: 11400, +11403: 11402, +11405: 11404, +11407: 11406, +11409: 11408, +11411: 11410, +11413: 11412, +11415: 11414, +11417: 11416, +11419: 11418, +11421: 11420, +11423: 11422, +11425: 11424, +11427: 11426, +11429: 11428, +11431: 11430, +11433: 11432, +11435: 11434, +11437: 11436, +11439: 11438, +11441: 11440, +11443: 11442, +11445: 11444, +11447: 11446, +11449: 11448, +11451: 11450, +11453: 11452, +11455: 11454, +11457: 11456, +11459: 11458, +11461: 11460, +11463: 11462, +11465: 11464, +11467: 11466, +11469: 11468, +11471: 11470, +11473: 11472, +11475: 11474, +11477: 11476, +11479: 11478, +11481: 11480, +11483: 11482, +11485: 11484, +11487: 11486, +11489: 11488, +11491: 11490, +11520: 4256, +11521: 4257, +11522: 4258, +11523: 4259, +11524: 4260, +11525: 4261, +11526: 4262, +11527: 4263, +11528: 4264, +11529: 4265, +11530: 4266, +11531: 4267, +11532: 4268, +11533: 4269, +11534: 4270, +11535: 4271, +11536: 4272, +11537: 4273, +11538: 4274, +11539: 4275, +11540: 4276, +11541: 4277, +11542: 4278, +11543: 4279, +11544: 4280, +11545: 4281, +11546: 4282, +11547: 4283, +11548: 4284, +11549: 4285, +11550: 4286, +11551: 4287, +11552: 4288, +11553: 4289, +11554: 4290, +11555: 4291, +11556: 4292, +11557: 4293, 65345: 65313, 65346: 65314, 65347: 65315, @@ -16381,6 +19276,8 @@ 66635: 66595, 66636: 66596, 66637: 66597, +66638: 66598, +66639: 66599, } _tolower = { @@ -16597,6 +19494,9 @@ 558: 559, 560: 561, 562: 563, +571: 572, +573: 410, +577: 660, 902: 940, 904: 941, 905: 942, @@ -16643,6 +19543,9 @@ 1004: 1005, 1006: 1007, 1012: 952, +1015: 1016, +1017: 1010, +1018: 1019, 1024: 1104, 1025: 1105, 1026: 1106, @@ -16761,6 +19664,7 @@ 1264: 1265, 1266: 1267, 1268: 1269, +1270: 1271, 1272: 1273, 1280: 1281, 1282: 1283, @@ -16808,6 +19712,44 @@ 1364: 1412, 1365: 1413, 1366: 1414, +4256: 11520, +4257: 11521, +4258: 11522, +4259: 11523, +4260: 11524, +4261: 11525, +4262: 11526, +4263: 11527, +4264: 11528, +4265: 11529, +4266: 11530, +4267: 11531, +4268: 11532, +4269: 11533, +4270: 11534, +4271: 11535, +4272: 11536, +4273: 11537, +4274: 11538, +4275: 11539, +4276: 11540, +4277: 11541, +4278: 11542, +4279: 11543, +4280: 11544, +4281: 11545, +4282: 11546, +4283: 11547, +4284: 11548, +4285: 11549, +4286: 11550, +4287: 11551, +4288: 11552, +4289: 11553, +4290: 11554, +4291: 11555, +4292: 11556, +4293: 11557, 7680: 7681, 7682: 7683, 7684: 7685, @@ -17069,6 +20011,103 @@ 9421: 9447, 9422: 9448, 9423: 9449, +11264: 11312, +11265: 11313, +11266: 11314, +11267: 11315, +11268: 11316, +11269: 11317, +11270: 11318, +11271: 11319, +11272: 11320, +11273: 11321, +11274: 11322, +11275: 11323, +11276: 11324, +11277: 11325, +11278: 11326, +11279: 11327, +11280: 11328, +11281: 11329, +11282: 11330, +11283: 11331, +11284: 11332, +11285: 11333, +11286: 11334, +11287: 11335, +11288: 11336, +11289: 11337, +11290: 11338, +11291: 11339, +11292: 11340, +11293: 11341, +11294: 11342, +11295: 11343, +11296: 11344, +11297: 11345, +11298: 11346, +11299: 11347, +11300: 11348, +11301: 11349, +11302: 11350, +11303: 11351, +11304: 11352, +11305: 11353, +11306: 11354, +11307: 11355, +11308: 11356, +11309: 11357, +11310: 11358, +11392: 11393, +11394: 11395, +11396: 11397, +11398: 11399, +11400: 11401, +11402: 11403, +11404: 11405, +11406: 11407, +11408: 11409, +11410: 11411, +11412: 11413, +11414: 11415, +11416: 11417, +11418: 11419, +11420: 11421, +11422: 11423, +11424: 11425, +11426: 11427, +11428: 11429, +11430: 11431, +11432: 11433, +11434: 11435, +11436: 11437, +11438: 11439, +11440: 11441, +11442: 11443, +11444: 11445, +11446: 11447, +11448: 11449, +11450: 11451, +11452: 11453, +11454: 11455, +11456: 11457, +11458: 11459, +11460: 11461, +11462: 11463, +11464: 11465, +11466: 11467, +11468: 11469, +11470: 11471, +11472: 11473, +11474: 11475, +11476: 11477, +11478: 11479, +11480: 11481, +11482: 11483, +11484: 11485, +11486: 11487, +11488: 11489, +11490: 11491, 65313: 65345, 65314: 65346, 65315: 65347, @@ -17133,6 +20172,8 @@ 66595: 66635, 66596: 66636, 66597: 66637, +66598: 66638, +66599: 66639, } _totitle = { @@ -17264,6 +20305,7 @@ 402: 401, 405: 502, 409: 408, +410: 573, 414: 544, 417: 416, 419: 418, @@ -17277,10 +20319,13 @@ 445: 444, 447: 503, 452: 453, +453: 453, 454: 453, 455: 456, +456: 456, 457: 456, 458: 459, +459: 459, 460: 459, 462: 461, 464: 463, @@ -17301,6 +20346,7 @@ 493: 492, 495: 494, 497: 498, +498: 498, 499: 498, 501: 500, 505: 504, @@ -17332,6 +20378,7 @@ 559: 558, 561: 560, 563: 562, +572: 571, 595: 385, 596: 390, 598: 393, @@ -17351,6 +20398,7 @@ 650: 433, 651: 434, 658: 439, +660: 577, 837: 921, 940: 902, 941: 904, @@ -17404,8 +20452,10 @@ 1007: 1006, 1008: 922, 1009: 929, -1010: 931, +1010: 1017, 1013: 917, +1016: 1015, +1019: 1018, 1072: 1040, 1073: 1041, 1074: 1042, @@ -17524,6 +20574,7 @@ 1265: 1264, 1267: 1266, 1269: 1268, +1271: 1270, 1273: 1272, 1281: 1280, 1283: 1282, @@ -17831,6 +20882,141 @@ 9447: 9421, 9448: 9422, 9449: 9423, +11312: 11264, +11313: 11265, +11314: 11266, +11315: 11267, +11316: 11268, +11317: 11269, +11318: 11270, +11319: 11271, +11320: 11272, +11321: 11273, +11322: 11274, +11323: 11275, +11324: 11276, +11325: 11277, +11326: 11278, +11327: 11279, +11328: 11280, +11329: 11281, +11330: 11282, +11331: 11283, +11332: 11284, +11333: 11285, +11334: 11286, +11335: 11287, +11336: 11288, +11337: 11289, +11338: 11290, +11339: 11291, +11340: 11292, +11341: 11293, +11342: 11294, +11343: 11295, +11344: 11296, +11345: 11297, +11346: 11298, +11347: 11299, +11348: 11300, +11349: 11301, +11350: 11302, +11351: 11303, +11352: 11304, +11353: 11305, +11354: 11306, +11355: 11307, +11356: 11308, +11357: 11309, +11358: 11310, +11393: 11392, +11395: 11394, +11397: 11396, +11399: 11398, +11401: 11400, +11403: 11402, +11405: 11404, +11407: 11406, +11409: 11408, +11411: 11410, +11413: 11412, +11415: 11414, +11417: 11416, +11419: 11418, +11421: 11420, +11423: 11422, +11425: 11424, +11427: 11426, +11429: 11428, +11431: 11430, +11433: 11432, +11435: 11434, +11437: 11436, +11439: 11438, +11441: 11440, +11443: 11442, +11445: 11444, +11447: 11446, +11449: 11448, +11451: 11450, +11453: 11452, +11455: 11454, +11457: 11456, +11459: 11458, +11461: 11460, +11463: 11462, +11465: 11464, +11467: 11466, +11469: 11468, +11471: 11470, +11473: 11472, +11475: 11474, +11477: 11476, +11479: 11478, +11481: 11480, +11483: 11482, +11485: 11484, +11487: 11486, +11489: 11488, +11491: 11490, +11520: 4256, +11521: 4257, +11522: 4258, +11523: 4259, +11524: 4260, +11525: 4261, +11526: 4262, +11527: 4263, +11528: 4264, +11529: 4265, +11530: 4266, +11531: 4267, +11532: 4268, +11533: 4269, +11534: 4270, +11535: 4271, +11536: 4272, +11537: 4273, +11538: 4274, +11539: 4275, +11540: 4276, +11541: 4277, +11542: 4278, +11543: 4279, +11544: 4280, +11545: 4281, +11546: 4282, +11547: 4283, +11548: 4284, +11549: 4285, +11550: 4286, +11551: 4287, +11552: 4288, +11553: 4289, +11554: 4290, +11555: 4291, +11556: 4292, +11557: 4293, 65345: 65313, 65346: 65314, 65347: 65315, @@ -17895,6 +21081,8 @@ 66635: 66595, 66636: 66596, 66637: 66597, +66638: 66598, +66639: 66599, } @@ -18252,6 +21440,7 @@ 1010: ' 03C2', 1012: ' 0398', 1013: ' 03B5', +1017: ' 03A3', 1024: '0415 0300', 1025: '0415 0308', 1027: '0413 0301', @@ -18386,6 +21575,105 @@ 4012: '0FAB 0FB7', 4025: '0F90 0FB5', 4134: '1025 102E', +4348: ' 10DC', +7468: ' 0041', +7469: ' 00C6', +7470: ' 0042', +7472: ' 0044', +7473: ' 0045', +7474: ' 018E', +7475: ' 0047', +7476: ' 0048', +7477: ' 0049', +7478: ' 004A', +7479: ' 004B', +7480: ' 004C', +7481: ' 004D', +7482: ' 004E', +7484: ' 004F', +7485: ' 0222', +7486: ' 0050', +7487: ' 0052', +7488: ' 0054', +7489: ' 0055', +7490: ' 0057', +7491: ' 0061', +7492: ' 0250', +7493: ' 0251', +7494: ' 1D02', +7495: ' 0062', +7496: ' 0064', +7497: ' 0065', +7498: ' 0259', +7499: ' 025B', +7500: ' 025C', +7501: ' 0067', +7503: ' 006B', +7504: ' 006D', +7505: ' 014B', +7506: ' 006F', +7507: ' 0254', +7508: ' 1D16', +7509: ' 1D17', +7510: ' 0070', +7511: ' 0074', +7512: ' 0075', +7513: ' 1D1D', +7514: ' 026F', +7515: ' 0076', +7516: ' 1D25', +7517: ' 03B2', +7518: ' 03B3', +7519: ' 03B4', +7520: ' 03C6', +7521: ' 03C7', +7522: ' 0069', +7523: ' 0072', +7524: ' 0075', +7525: ' 0076', +7526: ' 03B2', +7527: ' 03B3', +7528: ' 03C1', +7529: ' 03C6', +7530: ' 03C7', +7544: ' 043D', +7579: ' 0252', +7580: ' 0063', +7581: ' 0255', +7582: ' 00F0', +7583: ' 025C', +7584: ' 0066', +7585: ' 025F', +7586: ' 0261', +7587: ' 0265', +7588: ' 0268', +7589: ' 0269', +7590: ' 026A', +7591: ' 1D7B', +7592: ' 029D', +7593: ' 026D', +7594: ' 1D85', +7595: ' 029F', +7596: ' 0271', +7597: ' 0270', +7598: ' 0272', +7599: ' 0273', +7600: ' 0274', +7601: ' 0275', +7602: ' 0278', +7603: ' 0282', +7604: ' 0283', +7605: ' 01AB', +7606: ' 0289', +7607: ' 028A', +7608: ' 1D1C', +7609: ' 028B', +7610: ' 028C', +7611: ' 007A', +7612: ' 0290', +7613: ' 0291', +7614: ' 0292', +7615: ' 03B8', 7680: '0041 0325', 7681: '0061 0325', 7682: '0042 0307', @@ -18922,6 +22210,11 @@ 8332: ' 003D', 8333: ' 0028', 8334: ' 0029', +8336: ' 0061', +8337: ' 0065', +8338: ' 006F', +8339: ' 0078', +8340: ' 0259', 8360: ' 0052 0073', 8448: ' 0061 002F 0063', 8449: ' 0061 002F 0073', @@ -18968,6 +22261,8 @@ 8503: ' 05D2', 8504: ' 05D3', 8505: ' 0069', +8507: ' 0046 0041 0058', +8508: ' 03C0', 8509: ' 03B3', 8510: ' 0393', 8511: ' 03A0', @@ -19216,6 +22511,7 @@ 10869: ' 003D 003D', 10870: ' 003D 003D 003D', 10972: '2ADD 0338', +11631: ' 2D61', 11935: ' 6BCD', 12019: ' 9F9F', 12032: ' 4E00', @@ -19636,6 +22932,8 @@ 12826: ' 0028 1111 1161 0029', 12827: ' 0028 1112 1161 0029', 12828: ' 0028 110C 116E 0029', +12829: ' 0028 110B 1169 110C 1165 11AB 0029', +12830: ' 0028 110B 1169 1112 116E 0029', 12832: ' 0028 4E00 0029', 12833: ' 0028 4E8C 0029', 12834: ' 0028 4E09 0029', @@ -19672,6 +22970,7 @@ 12865: ' 0028 4F11 0029', 12866: ' 0028 81EA 0029', 12867: ' 0028 81F3 0029', +12880: ' 0050 0054 0045', 12881: ' 0032 0031', 12882: ' 0032 0032', 12883: ' 0032 0033', @@ -19715,6 +23014,9 @@ 12921: ' 1110 1161', 12922: ' 1111 1161', 12923: ' 1112 1161', +12924: ' 110E 1161 11B7 1100 1169', +12925: ' 110C 116E 110B 1174', +12926: ' 110B 116E', 12928: ' 4E00', 12929: ' 4E8C', 12930: ' 4E09', @@ -19791,6 +23093,10 @@ 13001: ' 0031 0030 6708', 13002: ' 0031 0031 6708', 13003: ' 0031 0032 6708', +13004: ' 0048 0067', +13005: ' 0065 0072 0067', +13006: ' 0065 0056', +13007: ' 004C 0054 0044', 13008: ' 30A2', 13009: ' 30A4', 13010: ' 30A6', @@ -19957,6 +23263,10 @@ 13172: ' 0062 0061 0072', 13173: ' 006F 0056', 13174: ' 0070 0063', +13175: ' 0064 006D', +13176: ' 0064 006D 00B2', +13177: ' 0064 006D 00B3', +13178: ' 0049 0055', 13179: ' 5E73 6210', 13180: ' 662D 548C', 13181: ' 5927 6B63', @@ -20056,6 +23366,8 @@ 13275: ' 0073 0072', 13276: ' 0053 0076', 13277: ' 0057 0062', +13278: ' 0056 2215 006D', +13279: ' 0041 2215 006D', 13280: ' 0031 65E5', 13281: ' 0032 65E5', 13282: ' 0033 65E5', @@ -20087,6 +23399,7 @@ 13308: ' 0032 0039 65E5', 13309: ' 0033 0030 65E5', 13310: ' 0033 0031 65E5', +13311: ' 0067 0061 006C', 63744: '8C48', 63745: '66F4', 63746: '8ECA', @@ -20436,6 +23749,112 @@ 64104: '96E3', 64105: '97FF', 64106: '983B', +64112: '4E26', +64113: '51B5', +64114: '5168', +64115: '4F80', +64116: '5145', +64117: '5180', +64118: '52C7', +64119: '52FA', +64120: '559D', +64121: '5555', +64122: '5599', +64123: '55E2', +64124: '585A', +64125: '58B3', +64126: '5944', +64127: '5954', +64128: '5A62', +64129: '5B28', +64130: '5ED2', +64131: '5ED9', +64132: '5F69', +64133: '5FAD', +64134: '60D8', +64135: '614E', +64136: '6108', +64137: '618E', +64138: '6160', +64139: '61F2', +64140: '6234', +64141: '63C4', +64142: '641C', +64143: '6452', +64144: '6556', +64145: '6674', +64146: '6717', +64147: '671B', +64148: '6756', +64149: '6B79', +64150: '6BBA', +64151: '6D41', +64152: '6EDB', +64153: '6ECB', +64154: '6F22', +64155: '701E', +64156: '716E', +64157: '77A7', +64158: '7235', +64159: '72AF', +64160: '732A', +64161: '7471', +64162: '7506', +64163: '753B', +64164: '761D', +64165: '761F', +64166: '76CA', +64167: '76DB', +64168: '76F4', +64169: '774A', +64170: '7740', +64171: '78CC', +64172: '7AB1', +64173: '7BC0', +64174: '7C7B', +64175: '7D5B', +64176: '7DF4', +64177: '7F3E', +64178: '8005', +64179: '8352', +64180: '83EF', +64181: '8779', +64182: '8941', +64183: '8986', +64184: '8996', +64185: '8ABF', +64186: '8AF8', +64187: '8ACB', +64188: '8B01', +64189: '8AFE', +64190: '8AED', +64191: '8B39', +64192: '8B8A', +64193: '8D08', +64194: '8F38', +64195: '9072', +64196: '9199', +64197: '9276', +64198: '967C', +64199: '96E3', +64200: '9756', +64201: '97DB', +64202: '97FF', +64203: '980B', +64204: '983B', +64205: '9B12', +64206: '9F9C', +64207: '2284A', +64208: '22844', +64209: '233D5', +64210: '3B9D', +64211: '4018', +64212: '4039', +64213: '25249', +64214: '25CD0', +64215: '27ED3', +64216: '9F43', +64217: '9F8E', 64256: ' 0066 0066', 64257: ' 0066 0069', 64258: ' 0066 006C', @@ -21085,6 +24504,16 @@ 65018: ' 0635 0644 0649 0020 0627 0644 0644 0647 0020 0639 0644 064A 0647 0020 0648 0633 0644 0645', 65019: ' 062C 0644 0020 062C 0644 0627 0644 0647', 65020: ' 0631 06CC 0627 0644', +65040: ' 002C', +65041: ' 3001', +65042: ' 3002', +65043: ' 003A', +65044: ' 003B', +65045: ' 0021', +65046: ' 003F', +65047: ' 3016', +65048: ' 3017', +65049: ' 2026', 65072: ' 2025', 65073: ' 2014', 65074: ' 2013', @@ -21106,6 +24535,8 @@ 65090: ' 300D', 65091: ' 300E', 65092: ' 300F', +65095: ' 005B', +65096: ' 005D', 65097: ' 203E', 65098: ' 203E', 65099: ' 203E', @@ -21698,6 +25129,7 @@ 119998: ' 0069', 119999: ' 006A', 120000: ' 006B', +120001: ' 006C', 120002: ' 006D', 120003: ' 006E', 120005: ' 0070', @@ -22167,6 +25599,8 @@ 120481: ' 0078', 120482: ' 0079', 120483: ' 007A', +120484: ' 0131', +120485: ' 0237', 120488: ' 0391', 120489: ' 0392', 120490: ' 0393', @@ -22611,7 +26045,7 @@ 194661: '59D8', 194662: '5A66', 194663: '36EE', -194664: '2136A', +194664: '36FC', 194665: '5B08', 194666: '5B3E', 194667: '5B3E', @@ -22623,7 +26057,7 @@ 194673: '21B18', 194674: '5BFF', 194675: '5C06', -194676: '5F33', +194676: '5F53', 194677: '5C22', 194678: '3781', 194679: '5C60', @@ -22794,7 +26228,7 @@ 194844: '7145', 194845: '24263', 194846: '719C', -194847: '43AB', +194847: '243AB', 194848: '7228', 194849: '7235', 194850: '7250', @@ -22858,7 +26292,7 @@ 194908: '2597C', 194909: '25AA7', 194910: '25AA7', -194911: '7AAE', +194911: '7AEE', 194912: '4202', 194913: '25BAB', 194914: '7BC6', @@ -22954,7 +26388,7 @@ 195004: '8728', 195005: '876B', 195006: '8786', -195007: '4D57', +195007: '45D7', 195008: '87E1', 195009: '8801', 195010: '45F9', @@ -25316,6 +28750,112 @@ 64104: [38627], 64105: [38911], 64106: [38971], +64112: [20006], +64113: [20917], +64114: [20840], +64115: [20352], +64116: [20805], +64117: [20864], +64118: [21191], +64119: [21242], +64120: [21917], +64121: [21845], +64122: [21913], +64123: [21986], +64124: [22618], +64125: [22707], +64126: [22852], +64127: [22868], +64128: [23138], +64129: [23336], +64130: [24274], +64131: [24281], +64132: [24425], +64133: [24493], +64134: [24792], +64135: [24910], +64136: [24840], +64137: [24974], +64138: [24928], +64139: [25074], +64140: [25140], +64141: [25540], +64142: [25628], +64143: [25682], +64144: [25942], +64145: [26228], +64146: [26391], +64147: [26395], +64148: [26454], +64149: [27513], +64150: [27578], +64151: [27969], +64152: [28379], +64153: [28363], +64154: [28450], +64155: [28702], +64156: [29038], +64157: [30631], +64158: [29237], +64159: [29359], +64160: [29482], +64161: [29809], +64162: [29958], +64163: [30011], +64164: [30237], +64165: [30239], +64166: [30410], +64167: [30427], +64168: [30452], +64169: [30538], +64170: [30528], +64171: [30924], +64172: [31409], +64173: [31680], +64174: [31867], +64175: [32091], +64176: [32244], +64177: [32574], +64178: [32773], +64179: [33618], +64180: [33775], +64181: [34681], +64182: [35137], +64183: [35206], +64184: [35222], +64185: [35519], +64186: [35576], +64187: [35531], +64188: [35585], +64189: [35582], +64190: [35565], +64191: [35641], +64192: [35722], +64193: [36104], +64194: [36664], +64195: [36978], +64196: [37273], +64197: [37494], +64198: [38524], +64199: [38627], +64200: [38742], +64201: [38875], +64202: [38911], +64203: [38923], +64204: [38971], +64205: [39698], +64206: [40860], +64207: [141386], +64208: [141380], +64209: [144341], +64210: [15261], +64211: [16408], +64212: [16441], +64213: [152137], +64214: [154832], +64215: [163539], +64216: [40771], +64217: [40846], 64285: [1497, 1460], 64287: [1522, 1463], 64298: [1513, 1473], @@ -25467,7 +29007,7 @@ 194661: [23000], 194662: [23142], 194663: [14062], -194664: [136042], +194664: [14076], 194665: [23304], 194666: [23358], 194667: [23358], @@ -25479,7 +29019,7 @@ 194673: [138008], 194674: [23551], 194675: [23558], -194676: [24371], +194676: [24403], 194677: [23586], 194678: [14209], 194679: [23648], @@ -25650,7 +29190,7 @@ 194844: [28997], 194845: [148067], 194846: [29084], -194847: [17323], +194847: [148395], 194848: [29224], 194849: [29237], 194850: [29264], @@ -25714,7 +29254,7 @@ 194908: [153980], 194909: [154279], 194910: [154279], -194911: [31406], +194911: [31470], 194912: [16898], 194913: [154539], 194914: [31686], @@ -25810,7 +29350,7 @@ 195004: [34600], 195005: [34667], 195006: [34694], -195007: [19799], +195007: [17879], 195008: [34785], 195009: [34817], 195010: [17913], @@ -26254,6 +29794,7 @@ 1010: [962], 1012: [920], 1013: [949], +1017: [931], 1024: [1045, 768], 1025: [1045, 776], 1027: [1043, 769], @@ -26388,6 +29929,105 @@ 4012: [4011, 4023], 4025: [3984, 4021], 4134: [4133, 4142], +4348: [4316], +7468: [65], +7469: [198], +7470: [66], +7472: [68], +7473: [69], +7474: [398], +7475: [71], +7476: [72], +7477: [73], +7478: [74], +7479: [75], +7480: [76], +7481: [77], +7482: [78], +7484: [79], +7485: [546], +7486: [80], +7487: [82], +7488: [84], +7489: [85], +7490: [87], +7491: [97], +7492: [592], +7493: [593], +7494: [7426], +7495: [98], +7496: [100], +7497: [101], +7498: [601], +7499: [603], +7500: [604], +7501: [103], +7503: [107], +7504: [109], +7505: [331], +7506: [111], +7507: [596], +7508: [7446], +7509: [7447], +7510: [112], +7511: [116], +7512: [117], +7513: [7453], +7514: [623], +7515: [118], +7516: [7461], +7517: [946], +7518: [947], +7519: [948], +7520: [966], +7521: [967], +7522: [105], +7523: [114], +7524: [117], +7525: [118], +7526: [946], +7527: [947], +7528: [961], +7529: [966], +7530: [967], +7544: [1085], +7579: [594], +7580: [99], +7581: [597], +7582: [240], +7583: [604], +7584: [102], +7585: [607], +7586: [609], +7587: [613], +7588: [616], +7589: [617], +7590: [618], +7591: [7547], +7592: [669], +7593: [621], +7594: [7557], +7595: [671], +7596: [625], +7597: [624], +7598: [626], +7599: [627], +7600: [628], +7601: [629], +7602: [632], +7603: [642], +7604: [643], +7605: [427], +7606: [649], +7607: [650], +7608: [7452], +7609: [651], +7610: [652], +7611: [122], +7612: [656], +7613: [657], +7614: [658], +7615: [952], 7680: [65, 805], 7681: [97, 805], 7682: [66, 775], @@ -26924,6 +30564,11 @@ 8332: [61], 8333: [40], 8334: [41], +8336: [97], +8337: [101], +8338: [111], +8339: [120], +8340: [601], 8360: [82, 115], 8448: [97, 47, 99], 8449: [97, 47, 115], @@ -26970,6 +30615,8 @@ 8503: [1490], 8504: [1491], 8505: [105], +8507: [70, 65, 88], +8508: [960], 8509: [947], 8510: [915], 8511: [928], @@ -27218,6 +30865,7 @@ 10869: [61, 61], 10870: [61, 61, 61], 10972: [10973, 824], +11631: [11617], 11935: [27597], 12019: [40863], 12032: [19968], @@ -27638,6 +31286,8 @@ 12826: [40, 4369, 4449, 41], 12827: [40, 4370, 4449, 41], 12828: [40, 4364, 4462, 41], +12829: [40, 4363, 4457, 4364, 4453, 4523, 41], +12830: [40, 4363, 4457, 4370, 4462, 41], 12832: [40, 19968, 41], 12833: [40, 20108, 41], 12834: [40, 19977, 41], @@ -27674,6 +31324,7 @@ 12865: [40, 20241, 41], 12866: [40, 33258, 41], 12867: [40, 33267, 41], +12880: [80, 84, 69], 12881: [50, 49], 12882: [50, 50], 12883: [50, 51], @@ -27717,6 +31368,9 @@ 12921: [4368, 4449], 12922: [4369, 4449], 12923: [4370, 4449], +12924: [4366, 4449, 4535, 4352, 4457], +12925: [4364, 4462, 4363, 4468], +12926: [4363, 4462], 12928: [19968], 12929: [20108], 12930: [19977], @@ -27793,6 +31447,10 @@ 13001: [49, 48, 26376], 13002: [49, 49, 26376], 13003: [49, 50, 26376], +13004: [72, 103], +13005: [101, 114, 103], +13006: [101, 86], +13007: [76, 84, 68], 13008: [12450], 13009: [12452], 13010: [12454], @@ -27959,6 +31617,10 @@ 13172: [98, 97, 114], 13173: [111, 86], 13174: [112, 99], +13175: [100, 109], +13176: [100, 109, 50], +13177: [100, 109, 51], +13178: [73, 85], 13179: [24179, 25104], 13180: [26157, 21644], 13181: [22823, 27491], @@ -28058,6 +31720,8 @@ 13275: [115, 114], 13276: [83, 118], 13277: [87, 98], +13278: [86, 8725, 109], +13279: [65, 8725, 109], 13280: [49, 26085], 13281: [50, 26085], 13282: [51, 26085], @@ -28089,6 +31753,7 @@ 13308: [50, 57, 26085], 13309: [51, 48, 26085], 13310: [51, 49, 26085], +13311: [103, 97, 108], 63744: [35912], 63745: [26356], 63746: [36554], @@ -28438,6 +32103,112 @@ 64104: [38627], 64105: [38911], 64106: [38971], +64112: [20006], +64113: [20917], +64114: [20840], +64115: [20352], +64116: [20805], +64117: [20864], +64118: [21191], +64119: [21242], +64120: [21917], +64121: [21845], +64122: [21913], +64123: [21986], +64124: [22618], +64125: [22707], +64126: [22852], +64127: [22868], +64128: [23138], +64129: [23336], +64130: [24274], +64131: [24281], +64132: [24425], +64133: [24493], +64134: [24792], +64135: [24910], +64136: [24840], +64137: [24974], +64138: [24928], +64139: [25074], +64140: [25140], +64141: [25540], +64142: [25628], +64143: [25682], +64144: [25942], +64145: [26228], +64146: [26391], +64147: [26395], +64148: [26454], +64149: [27513], +64150: [27578], +64151: [27969], +64152: [28379], +64153: [28363], +64154: [28450], +64155: [28702], +64156: [29038], +64157: [30631], +64158: [29237], +64159: [29359], +64160: [29482], +64161: [29809], +64162: [29958], +64163: [30011], +64164: [30237], +64165: [30239], +64166: [30410], +64167: [30427], +64168: [30452], +64169: [30538], +64170: [30528], +64171: [30924], +64172: [31409], +64173: [31680], +64174: [31867], +64175: [32091], +64176: [32244], +64177: [32574], +64178: [32773], +64179: [33618], +64180: [33775], +64181: [34681], +64182: [35137], +64183: [35206], +64184: [35222], +64185: [35519], +64186: [35576], +64187: [35531], +64188: [35585], +64189: [35582], +64190: [35565], +64191: [35641], +64192: [35722], +64193: [36104], +64194: [36664], +64195: [36978], +64196: [37273], +64197: [37494], +64198: [38524], +64199: [38627], +64200: [38742], +64201: [38875], +64202: [38911], +64203: [38923], +64204: [38971], +64205: [39698], +64206: [40860], +64207: [141386], +64208: [141380], +64209: [144341], +64210: [15261], +64211: [16408], +64212: [16441], +64213: [152137], +64214: [154832], +64215: [163539], +64216: [40771], +64217: [40846], 64256: [102, 102], 64257: [102, 105], 64258: [102, 108], @@ -29087,6 +32858,16 @@ 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], +65040: [44], +65041: [12289], +65042: [12290], +65043: [58], +65044: [59], +65045: [33], +65046: [63], +65047: [12310], +65048: [12311], +65049: [46, 46, 46], 65072: [46, 46], 65073: [8212], 65074: [8211], @@ -29108,6 +32889,8 @@ 65090: [12301], 65091: [12302], 65092: [12303], +65095: [91], +65096: [93], 65097: [32, 773], 65098: [32, 773], 65099: [32, 773], @@ -29700,6 +33483,7 @@ 119998: [105], 119999: [106], 120000: [107], +120001: [108], 120002: [109], 120003: [110], 120005: [112], @@ -30169,6 +33953,8 @@ 120481: [120], 120482: [121], 120483: [122], +120484: [305], +120485: [567], 120488: [913], 120489: [914], 120490: [915], @@ -30613,7 +34399,7 @@ 194661: [23000], 194662: [23142], 194663: [14062], -194664: [136042], +194664: [14076], 194665: [23304], 194666: [23358], 194667: [23358], @@ -30625,7 +34411,7 @@ 194673: [138008], 194674: [23551], 194675: [23558], -194676: [24371], +194676: [24403], 194677: [23586], 194678: [14209], 194679: [23648], @@ -30796,7 +34582,7 @@ 194844: [28997], 194845: [148067], 194846: [29084], -194847: [17323], +194847: [148395], 194848: [29224], 194849: [29237], 194850: [29264], @@ -30860,7 +34646,7 @@ 194908: [153980], 194909: [154279], 194910: [154279], -194911: [31406], +194911: [31470], 194912: [16898], 194913: [154539], 194914: [31686], @@ -30956,7 +34742,7 @@ 195004: [34600], 195005: [34667], 195006: [34694], -195007: [19799], +195007: [17879], 195008: [34785], 195009: [34817], 195010: [17913], From antocuni at codespeak.net Wed May 24 23:21:35 2006 From: antocuni at codespeak.net (antocuni at codespeak.net) Date: Wed, 24 May 2006 23:21:35 +0200 (CEST) Subject: [pypy-svn] r27663 - in pypy/dist/pypy/translator/cli: . src test Message-ID: <20060524212135.7A3441006E@code0.codespeak.net> Author: antocuni Date: Wed May 24 23:21:22 2006 New Revision: 27663 Added: pypy/dist/pypy/translator/cli/test/test_runtest.py (contents, props changed) Modified: pypy/dist/pypy/translator/cli/cts.py pypy/dist/pypy/translator/cli/src/pypylib.cs pypy/dist/pypy/translator/cli/test/runtest.py Log: Added the class CliTest: it is intended to be used togheter with classes in pypy.rpython.test.tool, so that tests written for rpython can be used for gencli with no effort. Modified: pypy/dist/pypy/translator/cli/cts.py ============================================================================== --- pypy/dist/pypy/translator/cli/cts.py (original) +++ pypy/dist/pypy/translator/cli/cts.py Wed May 24 23:21:22 2006 @@ -27,7 +27,8 @@ SignedLongLong: 'int64', UnsignedLongLong: 'unsigned int64', ootype.Bool: 'bool', - ootype.Float: 'float64', + ootype.Float: 'float64', + ootype.Char: 'char', ootype.Class: 'class [mscorlib]System.Type', # maps generic types to their ordinal Modified: pypy/dist/pypy/translator/cli/src/pypylib.cs ============================================================================== --- pypy/dist/pypy/translator/cli/src/pypylib.cs (original) +++ pypy/dist/pypy/translator/cli/src/pypylib.cs Wed May 24 23:21:22 2006 @@ -1,6 +1,27 @@ using System; using System.Collections.Generic; +namespace pypy.test +{ + public class Result + { + public static string ToPython(int x) { return x.ToString(); } + public static string ToPython(bool x) { return x.ToString(); } + public static string ToPython(double x) { return x.ToString(); } + public static string ToPython(char x) { return string.Format("'{0}'", x); } + + public static string ToPython(pypy.runtime.List lst) + { + // TODO: use StringBuilder instead + string res = "["; + foreach(T item in lst) + res += item.ToString() + ","; // XXX: only works for int, bool and double + res += "]"; + return res; + } + } +} + namespace pypy.runtime { public class Utils @@ -9,6 +30,7 @@ { return t.GetConstructor(new Type[0]).Invoke(new object[0]); } + } //The public interface List must implement is defined in Modified: pypy/dist/pypy/translator/cli/test/runtest.py ============================================================================== --- pypy/dist/pypy/translator/cli/test/runtest.py (original) +++ pypy/dist/pypy/translator/cli/test/runtest.py Wed May 24 23:21:22 2006 @@ -5,6 +5,11 @@ import py from pypy.tool.udir import udir from pypy.translator.translator import TranslationContext +from pypy.rpython.test.tool import BaseRtypingTest, OORtypeMixin +from pypy.rpython.lltypesystem.lltype import typeOf +from pypy.rpython.ootypesystem import ootype +from pypy.annotation.model import lltype_to_annotation + from pypy.translator.cli.option import getoption from pypy.translator.cli.gencli import GenCli from pypy.translator.cli.function import Function @@ -44,7 +49,7 @@ def render(self, ilasm): ilasm.begin_function('main', [('string[]', 'argv')], 'void', True, 'static') - # TODO: only int32 and bool are tested + # convert string arguments to their true type for i, arg in enumerate(self.graph.getargs()): ilasm.opcode('ldarg.0') ilasm.opcode('ldc.i4.%d' % i) @@ -55,13 +60,23 @@ ilasm.call(cts.graph_to_signature(self.graph)) - # print the result using the appropriate WriteLine overload - ret_type, ret_var = cts.llvar_to_cts(self.graph.getreturnvar()) - ilasm.call('void class [mscorlib]System.Console::WriteLine(%s)' % ret_type) + # convert result to a string containing a valid python expression + var = self.graph.getreturnvar() + ilasm.call('string class [pypylib]pypy.test.Result::%s' % + self.__output_method(var.concretetype)) + ilasm.call('void class [mscorlib]System.Console::WriteLine(string)') ilasm.opcode('ret') ilasm.end_function() self.db.pending_function(self.graph) + def __output_method(self, TYPE): + if isinstance(TYPE, ootype.List): + item_type = cts.lltype_to_cts(TYPE._ITEMTYPE) + return 'ToPython<%s> (class [pypylib]pypy.runtime.List`1)' % item_type + else: + type_ = cts.lltype_to_cts(TYPE) + return 'ToPython(%s)' % type_ + def __convert_method(self, arg_type): _conv = { 'int32': 'ToInt32', @@ -69,7 +84,8 @@ 'int64': 'ToInt64', 'unsigned int64': 'ToUInt64', 'bool': 'ToBoolean', - 'float64': 'ToDouble' + 'float64': 'ToDouble', + 'char': 'ToChar', } try: @@ -140,12 +156,24 @@ retval = mono.wait() assert retval == 0, stderr - ret_type, ret_var = cts.llvar_to_cts(self.graph.getreturnvar()) - if 'int' in ret_type: - return int(stdout) - elif ret_type == 'float64': - return float(stdout) - elif ret_type == 'bool': - return stdout.strip().lower() == 'true' - else: - assert False, 'Return type %s is not supported' % ret_type + return eval(stdout) +## ret_type, ret_var = cts.llvar_to_cts(self.graph.getreturnvar()) +## if 'int' in ret_type: +## return int(stdout) +## elif ret_type == 'float64': +## return float(stdout) +## elif ret_type == 'bool': +## return stdout.strip().lower() == 'true' +## else: +## assert False, 'Return type %s is not supported' % ret_type + + +class CliTest(BaseRtypingTest, OORtypeMixin): + def interpret(self, fn, args): + ann = [lltype_to_annotation(typeOf(x)) for x in args] + f = compile_function(fn, ann) + return f(*args) + + def interpret_raises(exc, func, args): + py.test.skip("CLI tests don't support interpret_raises") + Added: pypy/dist/pypy/translator/cli/test/test_runtest.py ============================================================================== --- (empty file) +++ pypy/dist/pypy/translator/cli/test/test_runtest.py Wed May 24 23:21:22 2006 @@ -0,0 +1,27 @@ +from pypy.translator.cli.test.runtest import CliTest +from pypy.translator.cli.test.runtest import FLOAT_PRECISION + +def ident(x): + return x + +class TestRunTest(CliTest): + + def test_int(self): + assert self.interpret(ident, [42]) == 42 + + def test_bool(self): + assert self.interpret(ident, [True]) == True + assert self.interpret(ident, [False]) == False + + def test_float(self): + x = 10/3.0 + res = self.interpret(ident, [x]) + assert round(x, FLOAT_PRECISION) == round(res, FLOAT_PRECISION) + + def test_char(self): + assert self.interpret(ident, ['a']) == 'a' + + def test_list(self): + def fn(): + return [1, 2, 3] + assert self.interpret(fn, []) == [1, 2, 3] From arigo at codespeak.net Thu May 25 12:44:56 2006 From: arigo at codespeak.net (arigo at codespeak.net) Date: Thu, 25 May 2006 12:44:56 +0200 (CEST) Subject: [pypy-svn] r27664 - in pypy/dist/pypy/objspace/std: . test Message-ID: <20060525104456.D27AC1005A@code0.codespeak.net> Author: arigo Date: Thu May 25 12:44:52 2006 New Revision: 27664 Modified: pypy/dist/pypy/objspace/std/test/test_stringobject.py pypy/dist/pypy/objspace/std/test/test_unicodeobject.py pypy/dist/pypy/objspace/std/unicodeobject.py Log: A corner case for str.replace and unicode.replace, mentioned on python-dev. Modified: pypy/dist/pypy/objspace/std/test/test_stringobject.py ============================================================================== --- pypy/dist/pypy/objspace/std/test/test_stringobject.py (original) +++ pypy/dist/pypy/objspace/std/test/test_stringobject.py Thu May 25 12:44:52 2006 @@ -252,6 +252,7 @@ assert 'abc'.replace('', '-', 3) == '-a-b-c' assert 'abc'.replace('', '-', 0) == 'abc' assert ''.replace('', '') == '' + assert ''.replace('', 'a') == 'a' assert 'abc'.replace('ab', '--', 0) == 'abc' assert 'abc'.replace('xy', '--') == 'abc' assert '123'.replace('123', '') == '' Modified: pypy/dist/pypy/objspace/std/test/test_unicodeobject.py ============================================================================== --- pypy/dist/pypy/objspace/std/test/test_unicodeobject.py (original) +++ pypy/dist/pypy/objspace/std/test/test_unicodeobject.py Thu May 25 12:44:52 2006 @@ -51,12 +51,21 @@ assert u'\na\nb\n'.splitlines(1) == [u'\n', u'a\n', u'b\n'] def test_zfill(self): - assert u'123'.zfill(6) == u'000123' assert u'123'.zfill(2) == u'123' + assert u'123'.zfill(3) == u'123' + assert u'123'.zfill(4) == u'0123' assert u'123'.zfill(6) == u'000123' assert u'+123'.zfill(2) == u'+123' + assert u'+123'.zfill(3) == u'+123' assert u'+123'.zfill(4) == u'+123' + assert u'+123'.zfill(5) == u'+0123' assert u'+123'.zfill(6) == u'+00123' + assert u'-123'.zfill(3) == u'-123' + assert u'-123'.zfill(4) == u'-123' + assert u'-123'.zfill(5) == u'-0123' + assert u''.zfill(3) == u'000' + assert u'34'.zfill(1) == u'34' + assert u'34'.zfill(4) == u'0034' def test_split(self): assert u"".split() == [] @@ -132,6 +141,36 @@ assert u'abc'.center(5, '*') == u'*abc*' # Python 2.4 raises(TypeError, u'abc'.center, 4, u'cba') + def test_title(self): + assert u"brown fox".title() == u"Brown Fox" + assert u"!brown fox".title() == u"!Brown Fox" + assert u"bROWN fOX".title() == u"Brown Fox" + assert u"Brown Fox".title() == u"Brown Fox" + assert u"bro!wn fox".title() == u"Bro!Wn Fox" + + def test_istitle(self): + assert u"".istitle() == False + assert u"!".istitle() == False + assert u"!!".istitle() == False + assert u"brown fox".istitle() == False + assert u"!brown fox".istitle() == False + assert u"bROWN fOX".istitle() == False + assert u"Brown Fox".istitle() == True + assert u"bro!wn fox".istitle() == False + assert u"Bro!wn fox".istitle() == False + assert u"!brown Fox".istitle() == False + assert u"!Brown Fox".istitle() == True + assert u"Brow&&&&N Fox".istitle() == True + assert u"!Brow&&&&n Fox".istitle() == False + + def test_capitalize(self): + assert u"brown fox".capitalize() == u"Brown fox" + assert u' hello '.capitalize() == u' hello ' + assert u'Hello '.capitalize() == u'Hello ' + assert u'hello '.capitalize() == u'Hello ' + assert u'aaaa'.capitalize() == u'Aaaa' + assert u'AaAa'.capitalize() == u'Aaaa' + def test_rjust(self): s = u"abc" assert s.rjust(2) == s @@ -160,6 +199,37 @@ assert u'abc'.ljust(5, '*') == u'abc**' # Python 2.4 raises(TypeError, u'abc'.ljust, 6, u'') + def test_replace(self): + assert u'one!two!three!'.replace(u'!', '@', 1) == u'one at two!three!' + assert u'one!two!three!'.replace('!', u'') == u'onetwothree' + assert u'one!two!three!'.replace(u'!', u'@', 2) == u'one at two@three!' + assert u'one!two!three!'.replace('!', '@', 3) == u'one at two@three@' + assert u'one!two!three!'.replace(u'!', '@', 4) == u'one at two@three@' + assert u'one!two!three!'.replace('!', u'@', 0) == u'one!two!three!' + assert u'one!two!three!'.replace(u'!', u'@') == u'one at two@three@' + assert u'one!two!three!'.replace('x', '@') == u'one!two!three!' + assert u'one!two!three!'.replace(u'x', '@', 2) == u'one!two!three!' + assert u'abc'.replace('', u'-') == u'-a-b-c-' + assert u'abc'.replace(u'', u'-', 3) == u'-a-b-c' + assert u'abc'.replace('', '-', 0) == u'abc' + assert u''.replace(u'', '') == u'' + assert u''.replace('', u'a') == u'a' + assert u'abc'.replace(u'ab', u'--', 0) == u'abc' + assert u'abc'.replace('xy', '--') == u'abc' + assert u'123'.replace(u'123', '') == u'' + assert u'123123'.replace('123', u'') == u'' + assert u'123x123'.replace(u'123', u'') == u'x' + + def test_strip(self): + s = u" a b " + assert s.strip() == u"a b" + assert s.rstrip() == u" a b" + assert s.lstrip() == u"a b " + assert u'xyzzyhelloxyzzy'.strip(u'xyz') == u'hello' + assert u'xyzzyhelloxyzzy'.lstrip('xyz') == u'helloxyzzy' + assert u'xyzzyhelloxyzzy'.rstrip(u'xyz') == u'xyzzyhello' + + def test_long_from_unicode(self): assert long(u'12345678901234567890') == 12345678901234567890 assert int(u'12345678901234567890') == 12345678901234567890 Modified: pypy/dist/pypy/objspace/std/unicodeobject.py ============================================================================== --- pypy/dist/pypy/objspace/std/unicodeobject.py (original) +++ pypy/dist/pypy/objspace/std/unicodeobject.py Thu May 25 12:44:52 2006 @@ -766,8 +766,6 @@ return space.newlist(parts) def _split(space, self, maxsplit): - if len(self) == 0: - return [] if maxsplit == 0: return [W_UnicodeObject(self)] index = 0 From mwh at codespeak.net Thu May 25 13:29:49 2006 From: mwh at codespeak.net (mwh at codespeak.net) Date: Thu, 25 May 2006 13:29:49 +0200 (CEST) Subject: [pypy-svn] r27666 - pypy/extradoc/talk/dls2006 Message-ID: <20060525112949.F40BA10057@code0.codespeak.net> Author: mwh Date: Thu May 25 13:29:48 2006 New Revision: 27666 Modified: pypy/extradoc/talk/dls2006/draft.txt Log: typo fixes, wording tweaks and a couple of comments. Modified: pypy/extradoc/talk/dls2006/draft.txt ============================================================================== --- pypy/extradoc/talk/dls2006/draft.txt (original) +++ pypy/extradoc/talk/dls2006/draft.txt Thu May 25 13:29:48 2006 @@ -2,10 +2,12 @@ Still Missing a Cool Title ************************************************************ +.. title ideas: Implementing Virtual Machines in Dynamic Languages? + :Abstract: - The PyPy project seeks to prove both on a research and on a - practical level the feasability of writing a virtual machine (VM) + The PyPy project seeks to prove both on a research and a + practical level the feasibility of writing a virtual machine (VM) for a dynamic language in a dynamic language - in this case, Python. The aim is to translate (i.e. compile) the VM to arbitrary target environments, ranging in level from C/Posix to Smalltalk/Squeak via @@ -17,7 +19,7 @@ programming language at various levels of our architecture and translation process. For each level, we design a corresponding type system and apply a generic type inference engine - for example, the - garbage collector (GC) is written in a style that manipulates + garbage collector is written in a style that manipulates simulated pointer and address objects, and when translated to C these operations become C-level pointer and address instructions. @@ -34,31 +36,33 @@ Despite the constant trend in the programming world towards portability and reusability, there are some areas in which it is still notoriously difficult to write flexible, portable, and reasonably efficient -programs. Virtual machines (VM) is one such area. Building +programs. The implementation of virtual machines is one such area. Building implementations of general programming languages, in particular highly dynamic ones, is typically a long-winded effort and produces a result -that is quite tailored to a specific platform. For this and other -reasons, standard platforms emerge; nowadays, a language implementor +that is quite [quite could be removed here?] tailored to a specific platform. +For this and other +reasons, standard platforms emerge; nowadays, a language implementer could cover most general platforms in use by writing three versions of -his VM: for C/Posix, for Java, and for CLI/.NET. This is, at least, the +his virtual machine: for C/Posix, for Java, and for CLI/.NET. This is, at least, the current situation of the Python programming language, where independent -volunteers developped and are now maintaining Java and .NET versions of +volunteers have developed and are now maintaining Java and .NET versions of Python, which follow the evolution of the "official" C version (CPython). However, we believe that platform standardization does not have to be a necessary component of this equation. We are basically using the -standard "metaprogramming" argument: if one could write the VM in a -very-high-level language, then the VM itself could be automatically +standard "meta-programming" argument: if one could write the VM in a +very high level language, then the VM itself could be automatically *translated* to any lower-level platform. Moreover by writing the VM in -such a language we would gain in flexibility and expressivity. +such a language we would gain in flexibility and expressiveness. PyPy achieves this goal without giving up on the efficiency of the compiled VMs. The key factors enabling this result are not to be found in recent advances in any particular research area - we are not using any sophisticated GC, any constraint-based type inference, any advanced -mega-programming concepts. Instead, we are following a novel overall -architecture: it is split in many levels of stepwise translation from +meta-programming [surely not mega-programming? :)] concepts. +Instead, we are following a novel overall +architecture: it is split into many levels of stepwise translation from the high-level source of the VM to the final target platform. Similar platforms can reuse many of these steps, while for very different platforms we have the option to perform very different translation @@ -66,13 +70,13 @@ different type system. Experiments also suggest a more mundane reason why such an approach is -only practical today: a typical translation takes about an hour on a +only practical today: a typical translation takes about half an hour on a modern PC and consumes close to 1GB of RAM. We shortly describe the architecture of PyPy in `section 2`_. In `section 3`_ we describe our approach of varying the type systems at various levels of the translation. `Section 4`_ gives an overview of -the type inferencer we developped. We present experimental results in +the type inference engine we developed. We present experimental results in `section 5`_ and future work directions in `section 6`_. In `section 7`_ we compare with related work, and finally we conclude in `section 8`_. @@ -88,7 +92,7 @@ the one hand an implementation of the Python programming language, mostly complete and compliant with the current version of the language, Python 2.4. Our current efforts are focused on the second part, which -is a translation toolsuite whose goal is, roughly speaking, to compile +is a translation tool-suite whose goal is, roughly speaking, to compile various subsets of Python to various environment. From arigo at codespeak.net Thu May 25 16:16:02 2006 From: arigo at codespeak.net (arigo at codespeak.net) Date: Thu, 25 May 2006 16:16:02 +0200 (CEST) Subject: [pypy-svn] r27667 - in pypy/dist/pypy/rpython/memory: . test Message-ID: <20060525141602.DC4401005A@code0.codespeak.net> Author: arigo Date: Thu May 25 16:16:00 2006 New Revision: 27667 Modified: pypy/dist/pypy/rpython/memory/gc.py pypy/dist/pypy/rpython/memory/test/test_transformed_gc.py Log: Cloning of varsized structures. Modified: pypy/dist/pypy/rpython/memory/gc.py ============================================================================== --- pypy/dist/pypy/rpython/memory/gc.py (original) +++ pypy/dist/pypy/rpython/memory/gc.py Thu May 25 16:16:00 2006 @@ -529,22 +529,47 @@ newhdr = oldhdr.next # abused to point to the copy if not newhdr: typeid >>= 1 + size = self.fixed_size(typeid) + # XXX! collect() at the beginning if the free heap is low if self.is_varsize(typeid): - raise NotImplementedError + itemsize = self.varsize_item_sizes(typeid) + offset_to_length = self.varsize_offset_to_length(typeid) + length = (oldobj_addr + + self.varsize_offset_to_length(typeid)).signed[0] + newobj = self.malloc_varsize(typeid, length, size, + itemsize, offset_to_length, + False) else: - size = self.fixed_size(typeid) - # XXX! collect() at the beginning if the free heap is low newobj = self.malloc_fixedsize(typeid, size, False) - newobj_addr = llmemory.cast_ptr_to_adr(newobj) - newhdr_addr = newobj_addr - size_gc_header - newhdr = llmemory.cast_adr_to_ptr(newhdr_addr, self.HDRPTR) - raw_memcopy(oldobj_addr, newobj_addr, size) - offsets = self.offsets_to_gc_pointers(typeid) + length = -1 + + newobj_addr = llmemory.cast_ptr_to_adr(newobj) + newhdr_addr = newobj_addr - size_gc_header + newhdr = llmemory.cast_adr_to_ptr(newhdr_addr, self.HDRPTR) + raw_memcopy(oldobj_addr, newobj_addr, size) + offsets = self.offsets_to_gc_pointers(typeid) + i = 0 + while i < len(offsets): + pointer_addr = newobj_addr + offsets[i] + stack.append(pointer_addr) + i += 1 + + if length > 0: + offsets = self.varsize_offsets_to_gcpointers_in_var_part( + typeid) + itemlength = self.varsize_item_sizes(typeid) + offset = self.varsize_offset_to_variable_part(typeid) + itembaseaddr = newobj_addr + offset i = 0 - while i < len(offsets): - pointer_addr = newobj_addr + offsets[i] - stack.append(pointer_addr) + while i < length: + item = itembaseaddr + itemlength * i + j = 0 + while j < len(offsets): + pointer_addr = item + offsets[j] + stack.append(pointer_addr) + j += 1 i += 1 + oldhdr.next = newhdr newobj_addr = llmemory.cast_ptr_to_adr(newhdr) + size_gc_header gcptr_addr.address[0] = newobj_addr Modified: pypy/dist/pypy/rpython/memory/test/test_transformed_gc.py ============================================================================== --- pypy/dist/pypy/rpython/memory/test/test_transformed_gc.py (original) +++ pypy/dist/pypy/rpython/memory/test/test_transformed_gc.py Thu May 25 16:16:00 2006 @@ -448,6 +448,41 @@ res = run([]) assert res == 111222333 + def test_cloning_varsize(self): + B = lltype.GcStruct('B', ('x', lltype.Signed)) + A = lltype.GcStruct('A', ('b', lltype.Ptr(B)), + ('more', lltype.Array(lltype.Ptr(B)))) + def make(n): + b = lltype.malloc(B) + b.x = n + a = lltype.malloc(A, 2) + a.b = b + a.more[0] = lltype.malloc(B) + a.more[0].x = n*10 + a.more[1] = lltype.malloc(B) + a.more[1].x = n*10+1 + return a + def func(): + oldpool = llop.gc_x_swap_pool(X_POOL_PTR, lltype.nullptr(X_POOL)) + a2 = make(22) + newpool = llop.gc_x_swap_pool(X_POOL_PTR, oldpool) + # clone a2 + a2ref = lltype.cast_opaque_ptr(llmemory.GCREF, a2) + clonedata = lltype.malloc(X_CLONE) + clonedata.gcobjectptr = a2ref + clonedata.pool = newpool + llop.gc_x_clone(lltype.Void, clonedata) + a2copyref = clonedata.gcobjectptr + a2copy = lltype.cast_opaque_ptr(lltype.Ptr(A), a2copyref) + a2copy.b.x = 44 + a2copy.more[0].x = 440 + a2copy.more[1].x = 441 + return a2.b.x * 1000000 + a2.more[0].x * 1000 + a2.more[1].x + + run = self.runner(func) + res = run([]) + assert res == 22220221 + def test_cloning_highlevel(self): from pypy.rpython import rgc class A: @@ -482,6 +517,33 @@ res = run([7, 0]) assert res == 1 + def test_cloning_highlevel_varsize(self): + from pypy.rpython import rgc + class A: + pass + def func(n, dummy): + lst = [A() for i in range(n)] + for a in lst: + a.value = 1 + lst2, newpool = rgc.gc_clone(lst, None) + for i in range(n): + a = A() + a.value = i + lst.append(a) + lst[i].value = 4 + i + lst2[i].value = 7 + i + + n = 0 + for a in lst: + n = n*10 + a.value + for a in lst2: + n = n*10 + a.value + return n + + run = self.runner(func, nbargs=2) + res = run([3, 0]) + assert res == 456012789 + def test_tree_cloning(self): import os # this makes a tree of calls. Each leaf stores its path (a linked From arigo at codespeak.net Thu May 25 16:21:22 2006 From: arigo at codespeak.net (arigo at codespeak.net) Date: Thu, 25 May 2006 16:21:22 +0200 (CEST) Subject: [pypy-svn] r27668 - in pypy/dist/pypy/module/stackless: . test Message-ID: <20060525142122.B0B9A10060@code0.codespeak.net> Author: arigo Date: Thu May 25 16:21:21 2006 New Revision: 27668 Modified: pypy/dist/pypy/module/stackless/interp_clonable.py pypy/dist/pypy/module/stackless/interp_coroutine.py pypy/dist/pypy/module/stackless/test/test_interp_clonable.py Log: Finished the draft ClonableCoroutine. Needed to reorganize a bit when hello() and goodbye() are called, to put the frames in the correct malloc pool. Modified: pypy/dist/pypy/module/stackless/interp_clonable.py ============================================================================== --- pypy/dist/pypy/module/stackless/interp_clonable.py (original) +++ pypy/dist/pypy/module/stackless/interp_clonable.py Thu May 25 16:21:21 2006 @@ -51,3 +51,7 @@ # we resume here twice. The following would need explanations about # why it returns the correct thing in both the parent and the child... return thunk.newcoroutine + +## from pypy.rpython.lltypesystem import lltype, lloperation +## lloperation.llop.debug_view(lltype.Void, current, thunk, +## lloperation.llop.gc_x_size_header(lltype.Signed)) Modified: pypy/dist/pypy/module/stackless/interp_coroutine.py ============================================================================== --- pypy/dist/pypy/module/stackless/interp_coroutine.py (original) +++ pypy/dist/pypy/module/stackless/interp_coroutine.py Thu May 25 16:21:21 2006 @@ -39,13 +39,8 @@ self.current = self.main = self.last = None def update(self, new): - old = self.current - if old is not None: - old.goodbye() - self.last, self.current = old, new + self.last, self.current = self.current, new frame, new.frame = new.frame, None - if new is not None: - new.hello() return frame class CoState(BaseCoState): @@ -124,7 +119,11 @@ def _bind(self, thunk): state = self.costate self.parent = state.current - state.last.frame = yield_current_frame_to_caller() + incoming_frame = yield_current_frame_to_caller() + left = state.last + left.frame = incoming_frame + left.goodbye() + self.hello() try: costate.do_things_to_do() thunk.call() @@ -146,8 +145,11 @@ # greenlets and tasklets have different ideas about this. raise CoroutineDamage state = self.costate - state.last.frame = state.update(self).switch() - # note that last gets updated before assignment! + incoming_frame = state.update(self).switch() + left = state.last + left.frame = incoming_frame + left.goodbye() + self.hello() costate.do_things_to_do() def kill(self): @@ -195,7 +197,7 @@ "Called when execution is transferred into this coroutine." def goodbye(self): - "Called just before execution is transferred away from this coroutine." + "Called just after execution is transferred away from this coroutine." costate = None costate = CoState() Modified: pypy/dist/pypy/module/stackless/test/test_interp_clonable.py ============================================================================== --- pypy/dist/pypy/module/stackless/test/test_interp_clonable.py (original) +++ pypy/dist/pypy/module/stackless/test/test_interp_clonable.py Thu May 25 16:21:21 2006 @@ -45,8 +45,42 @@ res = run([]) assert res == 1234546 + def test_clone_local_state(self): + class T(AbstractThunk): + def __init__(self, result): + self.result = result + def call(self): + localstate = [] + localstate.append(10) + self.result.append(2) + costate.main.switch() + localstate.append(20) + if localstate == [10, 20]: + self.result.append(4) + else: + self.result.append(0) + def f(): + result = [] + coro = ClonableCoroutine() + coro.bind(T(result)) + result.append(1) + coro.switch() + coro2 = coro.clone() + result.append(3) + coro2.switch() + result.append(5) + coro.switch() + result.append(6) + n = 0 + for i in result: + n = n*10 + i + return n + + run = self.runner(f) + res = run([]) + assert res == 1234546 + def test_fork(self): - import py; py.test.skip("in-progress") class T(AbstractThunk): def __init__(self, result): self.result = result From antocuni at codespeak.net Thu May 25 16:42:26 2006 From: antocuni at codespeak.net (antocuni at codespeak.net) Date: Thu, 25 May 2006 16:42:26 +0200 (CEST) Subject: [pypy-svn] r27669 - in pypy/dist/pypy/translator/cli: . src test Message-ID: <20060525144226.E3BFB10060@code0.codespeak.net> Author: antocuni Date: Thu May 25 16:42:15 2006 New Revision: 27669 Modified: pypy/dist/pypy/translator/cli/cts.py pypy/dist/pypy/translator/cli/database.py pypy/dist/pypy/translator/cli/ilgenerator.py pypy/dist/pypy/translator/cli/record.py pypy/dist/pypy/translator/cli/src/pypylib.cs pypy/dist/pypy/translator/cli/test/runtest.py pypy/dist/pypy/translator/cli/test/test_runtest.py Log: - Added support for tuple constants. - Added support for function that return tuples in runtest.CliTest, and some methods for compatibility with OORtypeMixin. Modified: pypy/dist/pypy/translator/cli/cts.py ============================================================================== --- pypy/dist/pypy/translator/cli/cts.py (original) +++ pypy/dist/pypy/translator/cli/cts.py Thu May 25 16:42:15 2006 @@ -79,6 +79,8 @@ return 'void' # TODO: is it correct to ignore StaticMethod? elif isinstance(t, ootype.List): item_type = self.lltype_to_cts(t._ITEMTYPE) + if item_type == 'void': # special case: CLI doesn't allow List of void; use int instead + item_type = 'int32' return self.__class(PYPY_LIST % item_type, include_class) elif isinstance(t, ootype.Dict): key_type = self.lltype_to_cts(t._KEYTYPE) Modified: pypy/dist/pypy/translator/cli/database.py ============================================================================== --- pypy/dist/pypy/translator/cli/database.py (original) +++ pypy/dist/pypy/translator/cli/database.py Thu May 25 16:42:15 2006 @@ -68,7 +68,7 @@ return '%s.%s::%s' % (CONST_NAMESPACE, CONST_CLASS, name) def gen_constants(self, ilasm): - if not ilasm . show_const (): + if not ilasm.show_const(): return ilasm.begin_namespace(CONST_NAMESPACE) ilasm.begin_class(CONST_CLASS) @@ -83,7 +83,7 @@ for const, name in self.consts.iteritems(): const.init(ilasm) type_ = const.get_type() - ilasm.set_static_field ( type_, CONST_NAMESPACE, CONST_CLASS, name ) + ilasm.set_static_field (type_, CONST_NAMESPACE, CONST_CLASS, name) ilasm.ret() ilasm.end_function() @@ -102,10 +102,31 @@ if isinstance(const, ootype._instance): return InstanceConst(db, const, static_type) + elif isinstance(const, ootype._record): + return RecordConst(db, const) else: assert False, 'Unknown constant: %s' % const make = staticmethod(make) - + + def load(db, TYPE, value, ilasm): + # TODO: code duplicated from function.py, refactoring needed + if TYPE is ootype.Void: + pass + elif TYPE is ootype.Bool: + ilasm.opcode('ldc.i4', str(int(value))) + elif TYPE is ootype.Float: + ilasm.opcode('ldc.r8', repr(value)) + elif TYPE in (ootype.Signed, ootype.Unsigned): + ilasm.opcode('ldc.i4', str(value)) + elif TYPE in (ootype.SignedLongLong, ootype.UnsignedLongLong): + ilasm.opcode('ldc.i8', str(value)) + else: + cts = CTS(db) + name = db.record_const(value) + cts_type = cts.lltype_to_cts(TYPE) + ilasm.opcode('ldsfld %s %s' % (cts_type, name)) + load = staticmethod(load) + def get_name(self): pass @@ -115,6 +136,34 @@ def init(self, ilasm): pass +class RecordConst(AbstractConst): + def __init__(self, db, record): + self.db = db + self.cts = CTS(db) + self.record = record + + def __hash__(self): + return hash(self.record) + + def __eq__(self, other): + return self.record == other.record + + def get_name(self): + return 'Record' + + def get_type(self): + return self.cts.lltype_to_cts(self.record._TYPE) + + def init(self, ilasm): + class_name = self.record._TYPE._name + ilasm.new('instance void class %s::.ctor()' % class_name) + for f_name, (FIELD_TYPE, f_default) in self.record._TYPE._fields.iteritems(): + f_type = self.cts.lltype_to_cts(FIELD_TYPE) + value = self.record._items[f_name] + ilasm.opcode('dup') + AbstractConst.load(self.db, FIELD_TYPE, value, ilasm) + ilasm.set_field((f_type, class_name, f_name)) + class InstanceConst(AbstractConst): def __init__(self, db, obj, static_type): self.cts = CTS(db) Modified: pypy/dist/pypy/translator/cli/ilgenerator.py ============================================================================== --- pypy/dist/pypy/translator/cli/ilgenerator.py (original) +++ pypy/dist/pypy/translator/cli/ilgenerator.py Thu May 25 16:42:15 2006 @@ -143,7 +143,7 @@ def set_field(self, field_data ): self.opcode('stfld %s %s::%s' % field_data ) - def get_field(self,field_data): + def get_field(self, field_data): self.opcode('ldfld %s %s::%s' % field_data ) def load_set_field(self, cts_type, name): @@ -158,7 +158,7 @@ def ret(self): self.opcode('ret') - def castclass(self,cts_type): + def castclass(self, cts_type): self.opcode('castclass', cts_type) def load_self(self): Modified: pypy/dist/pypy/translator/cli/record.py ============================================================================== --- pypy/dist/pypy/translator/cli/record.py (original) +++ pypy/dist/pypy/translator/cli/record.py Thu May 25 16:42:15 2006 @@ -11,8 +11,8 @@ trans = string.maketrans('<>(), ', '______') name = ['Record'] - for f_name, (f_type, f_default) in record._fields.iteritems(): - type_name = f_type._short_name().translate(trans) + for f_name, (FIELD_TYPE, f_default) in record._fields.iteritems(): + type_name = FIELD_TYPE._short_name().translate(trans) name.append(type_name) self.name = '__'.join(name) record._name = self.name @@ -36,12 +36,13 @@ self.ilasm = ilasm ilasm.begin_class(self.name, self.get_base_class()) - for f_name, (f_type, f_default) in self.record._fields.iteritems(): - cts_type = self.cts.lltype_to_cts(f_type) + for f_name, (FIELD_TYPE, f_default) in self.record._fields.iteritems(): + cts_type = self.cts.lltype_to_cts(FIELD_TYPE) if cts_type != 'void': ilasm.field(f_name, cts_type) self._ctor() + self._toString() ilasm.end_class() self.db.record_class(self.record, self.name) @@ -53,3 +54,25 @@ self.ilasm.opcode('ret') self.ilasm.end_function() + def _toString(self): + # only for testing purposes, and only if the Record represents a tuple + from pypy.translator.cli.test.runtest import format_object + + for f_name in self.record._fields: + if not f_name.startswith('item'): + return # it's not a tuple + + self.ilasm.begin_function('ToString', [], 'string', False, 'virtual', 'instance', 'default') + self.ilasm.opcode('ldstr', '""') + for i in xrange(len(self.record._fields)): + f_name = 'item%d' % i + FIELD_TYPE, f_default = self.record._fields[f_name] + self.ilasm.opcode('ldarg.0') + f_type = self.cts.lltype_to_cts(FIELD_TYPE) + self.ilasm.get_field((f_type, self.name, f_name)) + format_object(FIELD_TYPE, self.ilasm) + self.ilasm.call('string string::Concat(string, string)') + self.ilasm.opcode('ldstr ", "') + self.ilasm.call('string string::Concat(string, string)') + self.ilasm.opcode('ret') + self.ilasm.end_function() Modified: pypy/dist/pypy/translator/cli/src/pypylib.cs ============================================================================== --- pypy/dist/pypy/translator/cli/src/pypylib.cs (original) +++ pypy/dist/pypy/translator/cli/src/pypylib.cs Thu May 25 16:42:15 2006 @@ -9,16 +9,6 @@ public static string ToPython(bool x) { return x.ToString(); } public static string ToPython(double x) { return x.ToString(); } public static string ToPython(char x) { return string.Format("'{0}'", x); } - - public static string ToPython(pypy.runtime.List lst) - { - // TODO: use StringBuilder instead - string res = "["; - foreach(T item in lst) - res += item.ToString() + ","; // XXX: only works for int, bool and double - res += "]"; - return res; - } } } @@ -37,6 +27,16 @@ // rpython.ootypesystem.ootype.List.GENERIC_METHODS public class List: System.Collections.Generic.List { + public override string ToString() + { + // TODO: use StringBuilder instead + string res = "["; + foreach(T item in this) + res += item.ToString() + ","; // XXX: doesn't work for chars + res += "]"; + return res; + } + public int ll_length() { return this.Count; Modified: pypy/dist/pypy/translator/cli/test/runtest.py ============================================================================== --- pypy/dist/pypy/translator/cli/test/runtest.py (original) +++ pypy/dist/pypy/translator/cli/test/runtest.py Thu May 25 16:42:15 2006 @@ -33,6 +33,14 @@ else: assert res1 == res2 +def format_object(TYPE, ilasm): + if isinstance(TYPE, ootype.BuiltinType): + ilasm.call_method('string object::ToString()', virtual=True) + else: + type_ = cts.lltype_to_cts(TYPE) + ilasm.call('string class [pypylib]pypy.test.Result::ToPython(%s)' % type_) + + class TestEntryPoint(Node): """ This class produces a 'main' method that converts its arguments @@ -61,22 +69,13 @@ ilasm.call(cts.graph_to_signature(self.graph)) # convert result to a string containing a valid python expression - var = self.graph.getreturnvar() - ilasm.call('string class [pypylib]pypy.test.Result::%s' % - self.__output_method(var.concretetype)) + TYPE = self.graph.getreturnvar().concretetype + format_object(TYPE, ilasm) ilasm.call('void class [mscorlib]System.Console::WriteLine(string)') ilasm.opcode('ret') ilasm.end_function() self.db.pending_function(self.graph) - def __output_method(self, TYPE): - if isinstance(TYPE, ootype.List): - item_type = cts.lltype_to_cts(TYPE._ITEMTYPE) - return 'ToPython<%s> (class [pypylib]pypy.runtime.List`1)' % item_type - else: - type_ = cts.lltype_to_cts(TYPE) - return 'ToPython(%s)' % type_ - def __convert_method(self, arg_type): _conv = { 'int32': 'ToInt32', @@ -156,17 +155,18 @@ retval = mono.wait() assert retval == 0, stderr - return eval(stdout) -## ret_type, ret_var = cts.llvar_to_cts(self.graph.getreturnvar()) -## if 'int' in ret_type: -## return int(stdout) -## elif ret_type == 'float64': -## return float(stdout) -## elif ret_type == 'bool': -## return stdout.strip().lower() == 'true' -## else: -## assert False, 'Return type %s is not supported' % ret_type - + res = eval(stdout) + if isinstance(res, tuple): + res = StructTuple(res) # so tests can access tuple elements with .item0, .item1, etc. + return res + +class StructTuple(tuple): + def __getattr__(self, name): + if name.startswith('item'): + i = int(name[len('item'):]) + return self[i] + else: + raise AttributeError, name class CliTest(BaseRtypingTest, OORtypeMixin): def interpret(self, fn, args): @@ -177,3 +177,11 @@ def interpret_raises(exc, func, args): py.test.skip("CLI tests don't support interpret_raises") + def ll_to_string(self, s): + py.test.skip('ll_to_string not supported, yet') + + def ll_to_list(self, l): + return l + + def class_name(self, value): + py.test.skip('class_name not supported, yet') Modified: pypy/dist/pypy/translator/cli/test/test_runtest.py ============================================================================== --- pypy/dist/pypy/translator/cli/test/test_runtest.py (original) +++ pypy/dist/pypy/translator/cli/test/test_runtest.py Thu May 25 16:42:15 2006 @@ -25,3 +25,8 @@ def fn(): return [1, 2, 3] assert self.interpret(fn, []) == [1, 2, 3] + + def test_tuple(self): + def fn(): + return 1, 2 + assert self.interpret(fn, []) == (1, 2) From arigo at codespeak.net Thu May 25 16:50:55 2006 From: arigo at codespeak.net (arigo at codespeak.net) Date: Thu, 25 May 2006 16:50:55 +0200 (CEST) Subject: [pypy-svn] r27670 - pypy/extradoc/talk/dls2006 Message-ID: <20060525145055.8514E10061@code0.codespeak.net> Author: arigo Date: Thu May 25 16:50:54 2006 New Revision: 27670 Modified: pypy/extradoc/talk/dls2006/draft.txt Log: A short architecture section. Modified: pypy/extradoc/talk/dls2006/draft.txt ============================================================================== --- pypy/extradoc/talk/dls2006/draft.txt (original) +++ pypy/extradoc/talk/dls2006/draft.txt Thu May 25 16:50:54 2006 @@ -88,13 +88,29 @@ ============================================================ -XXX it contains on -the one hand an implementation of the Python programming language, -mostly complete and compliant with the current version of the language, -Python 2.4. Our current efforts are focused on the second part, which -is a translation tool-suite whose goal is, roughly speaking, to compile -various subsets of Python to various environment. +There are two major components in PyPy: +1. the *Standard Interpreter*: an implementation of the Python programming +language, mostly complete and compliant with the current version of the +language, Python 2.4. + +2. the *Translation Process*: a translation tool-suite whose goal is to +compile subsets of Python to various environment. + +In particular, we have defined a subset of the Python language called +"restricted Python" or RPython. This sublanguage is not restricted +syntactically, but only in the way it manipulates objects of different +types. The restrictions are a compromise between the expressivity and +the need to statically infer enough types to generate efficient code. +The foremost purpose of the translation tool-suite is to compile such +RPython programs to a variety of different platforms. + +Our current efforts, and the present paper, focus on this tool-suite. +We will not talk about the Standard Interpreter component of PyPy in the +sequel, other than mention that it is written in RPython and can thus be +translated. At close to 90'000 lines of code, it is the largest RPython +program that we have translated so far. More information can be found +in `[1]`_. .. _`section 3`: @@ -160,3 +176,6 @@ XXX + + +.. _`[1]`: http://codespeak.net/pypy/dist/pypy/doc/architecture.html#the-standard-interpreter From tismer at codespeak.net Thu May 25 17:56:18 2006 From: tismer at codespeak.net (tismer at codespeak.net) Date: Thu, 25 May 2006 17:56:18 +0200 (CEST) Subject: [pypy-svn] r27674 - pypy/dist/pypy/rpython Message-ID: <20060525155618.33E4410053@code0.codespeak.net> Author: tismer Date: Thu May 25 17:56:17 2006 New Revision: 27674 Modified: pypy/dist/pypy/rpython/rlist.py Log: set a reminder for a missing spot in rlist Modified: pypy/dist/pypy/rpython/rlist.py ============================================================================== --- pypy/dist/pypy/rpython/rlist.py (original) +++ pypy/dist/pypy/rpython/rlist.py Thu May 25 17:56:17 2006 @@ -258,6 +258,10 @@ def rtype_alloc_and_set(hop): r_list = hop.r_result + # XXX the special case for pyobj_repr needs to be implemented here as well + # will probably happen during NFS + if r_list == robject.pyobj_repr: + raise Exception, 'please implement this!' v_count, v_item = hop.inputargs(Signed, r_list.item_repr) cLIST = hop.inputconst(Void, r_list.LIST) return hop.gendirectcall(ll_alloc_and_set, cLIST, v_count, v_item) From tismer at codespeak.net Thu May 25 18:02:49 2006 From: tismer at codespeak.net (tismer at codespeak.net) Date: Thu, 25 May 2006 18:02:49 +0200 (CEST) Subject: [pypy-svn] r27675 - pypy/extradoc/sprintinfo/ddorf2006 Message-ID: <20060525160249.342EC1005A@code0.codespeak.net> Author: tismer Date: Thu May 25 18:02:48 2006 New Revision: 27675 Modified: pypy/extradoc/sprintinfo/ddorf2006/people.txt Log: coming 1st - 9th. No idea about accommodation, yet Modified: pypy/extradoc/sprintinfo/ddorf2006/people.txt ============================================================================== --- pypy/extradoc/sprintinfo/ddorf2006/people.txt (original) +++ pypy/extradoc/sprintinfo/ddorf2006/people.txt Thu May 25 18:02:48 2006 @@ -16,6 +16,7 @@ Maciej Fijalkowski 3rd-9th cfbolz Anders Chrigstroem 1st - 9th ? Samuele Pedroni 1st - 9th ? +Christian Tismer 1st - 9th ? Antonio Cuni 1st - 9th cfbolz Anders Lehmann 2nd - 9th ? ==================== ============== ===================== From pedronis at codespeak.net Thu May 25 18:08:38 2006 From: pedronis at codespeak.net (pedronis at codespeak.net) Date: Thu, 25 May 2006 18:08:38 +0200 (CEST) Subject: [pypy-svn] r27677 - pypy/extradoc/talk/dls2006 Message-ID: <20060525160838.57B411005A@code0.codespeak.net> Author: pedronis Date: Thu May 25 18:08:36 2006 New Revision: 27677 Modified: pypy/extradoc/talk/dls2006/draft.txt Log: some tweaks and comments about what is alreday there Modified: pypy/extradoc/talk/dls2006/draft.txt ============================================================================== --- pypy/extradoc/talk/dls2006/draft.txt (original) +++ pypy/extradoc/talk/dls2006/draft.txt Thu May 25 18:08:36 2006 @@ -33,45 +33,68 @@ ============================================================ -Despite the constant trend in the programming world towards portability -and reusability, there are some areas in which it is still notoriously -difficult to write flexible, portable, and reasonably efficient -programs. The implementation of virtual machines is one such area. Building -implementations of general programming languages, in particular highly -dynamic ones, is typically a long-winded effort and produces a result -that is quite [quite could be removed here?] tailored to a specific platform. -For this and other -reasons, standard platforms emerge; nowadays, a language implementer -could cover most general platforms in use by writing three versions of -his virtual machine: for C/Posix, for Java, and for CLI/.NET. This is, at least, the -current situation of the Python programming language, where independent -volunteers have developed and are now maintaining Java and .NET versions of -Python, which follow the evolution of the "official" C version -(CPython). +Despite the constant trend in the programming world towards +portability and reusability, there are some areas in which it is still +notoriously difficult to write flexible, portable, and reasonably +efficient programs. The implementation of virtual machines is one +such area. Building implementations of general programming languages, +in particular highly dynamic ones, using a classic direct coding +approach, is typically a long-winded effort and produces a result that +is quite [quite could be removed here?] tailored to a specific +platform and where architectural decisions (e.g. about GC) are spread +across the code in a pervasive and invasive way. + +For this and other reasons, standard platforms emerge; nowadays, a +language implementer could cover most general platforms in use by +writing three versions of his virtual machine: for C/Posix, for Java, +and for CLI/.NET. This is, at least, the current situation of the +Python programming language, where independent volunteers have +developed and are now maintaining Java and .NET versions of Python, +which follow the evolution of the "official" C version (CPython). -However, we believe that platform standardization does not have to be a -necessary component of this equation. We are basically using the +However, we believe that platform standardization does not have to be +a necessary component of this equation. We are basically using the standard "meta-programming" argument: if one could write the VM in a very high level language, then the VM itself could be automatically -*translated* to any lower-level platform. Moreover by writing the VM in -such a language we would gain in flexibility and expressiveness. +*translated* to any lower-level platform. Moreover by writing the VM +in such a language we would gain in flexibility in architectural +choices and expressiveness. PyPy achieves this goal without giving up on the efficiency of the -compiled VMs. The key factors enabling this result are not to be found +compiled VMs. + + + + +The key factors enabling this result are not to be found in recent advances in any particular research area - we are not using any sophisticated GC, any constraint-based type inference, any advanced -meta-programming [surely not mega-programming? :)] concepts. -Instead, we are following a novel overall -architecture: it is split into many levels of stepwise translation from -the high-level source of the VM to the final target platform. Similar -platforms can reuse many of these steps, while for very different -platforms we have the option to perform very different translation -steps. Each step reuses a common type inference component, but with a -different type system. +meta-programmingconcepts. +[this claim formulated this way is confusing, the GC aspect is marginal +and we could adopt a sophisticated GC, the constraint based type inference +is pertinent, but the meta-programming is a bit too vague, +there's no accepted definition of what should be considered advanced meta-programming, and what we do is meta-programming for some definition, +I would just cite the constraint type inference as example, and be happy] + +Instead, we are following a novel overall architecture: it is split +into many levels of stepwise translation from the high-level source of +the VM to the final target platform. Similar platforms can reuse many +of these steps, while for very different platforms we have the option +to perform very different translation steps. Each step reuses a +common type inference component, but with a different type +system. Steps are based on flow graph transformation and rewriting and +by augmenting the program with further implementation code written in +Python and analysed with the suitable type system. For the various +analyses used, not only type inference, we try to formulate them as +abstract interpretation, mitigating the potential efficiency problem +by wise choices and compromises for the domain used, but gaining much +more freedom and controllability without needing to think +sophisticated setup transformations to prepare the input for more +tailored algorithms. Experiments also suggest a more mundane reason why such an approach is -only practical today: a typical translation takes about half an hour on a -modern PC and consumes close to 1GB of RAM. +only practical today: a typical translation takes about half an hour +on a modern PC and consumes close to 1GB of RAM. We shortly describe the architecture of PyPy in `section 2`_. In `section 3`_ we describe our approach of varying the type systems at From pedronis at codespeak.net Thu May 25 18:13:53 2006 From: pedronis at codespeak.net (pedronis at codespeak.net) Date: Thu, 25 May 2006 18:13:53 +0200 (CEST) Subject: [pypy-svn] r27679 - pypy/extradoc/talk/dls2006 Message-ID: <20060525161353.9B3B21005A@code0.codespeak.net> Author: pedronis Date: Thu May 25 18:13:52 2006 New Revision: 27679 Modified: pypy/extradoc/talk/dls2006/draft.txt Log: too much whitespace Modified: pypy/extradoc/talk/dls2006/draft.txt ============================================================================== --- pypy/extradoc/talk/dls2006/draft.txt (original) +++ pypy/extradoc/talk/dls2006/draft.txt Thu May 25 18:13:52 2006 @@ -63,9 +63,6 @@ PyPy achieves this goal without giving up on the efficiency of the compiled VMs. - - - The key factors enabling this result are not to be found in recent advances in any particular research area - we are not using any sophisticated GC, any constraint-based type inference, any advanced From ale at codespeak.net Thu May 25 19:05:02 2006 From: ale at codespeak.net (ale at codespeak.net) Date: Thu, 25 May 2006 19:05:02 +0200 (CEST) Subject: [pypy-svn] r27680 - in pypy/dist/pypy/lib/pyontology: . test Message-ID: <20060525170502.7160810057@code0.codespeak.net> Author: ale Date: Thu May 25 19:05:01 2006 New Revision: 27680 Modified: pypy/dist/pypy/lib/pyontology/constraint_classes.py pypy/dist/pypy/lib/pyontology/pyontology.py pypy/dist/pypy/lib/pyontology/test/test_ontology.py Log: Bugfixes. There is still a dict order dependant bug --- tomorrow maybe Modified: pypy/dist/pypy/lib/pyontology/constraint_classes.py ============================================================================== --- pypy/dist/pypy/lib/pyontology/constraint_classes.py (original) +++ pypy/dist/pypy/lib/pyontology/constraint_classes.py Thu May 25 19:05:01 2006 @@ -1,4 +1,5 @@ from logilab.constraint.propagation import AbstractDomain, AbstractConstraint, ConsistencyFailure +from rdflib import URIRef class OwlConstraint(AbstractConstraint): @@ -47,7 +48,7 @@ self.variable = variable def narrow(self, domains): - if domains[self.variable] != []: + if domains[self.variable].getValues() != []: raise ConsistencyFailure class SubClassConstraint(AbstractConstraint): @@ -88,11 +89,21 @@ if i in vals2: raise ConsistencyFailure() -class ComplementClassConstraint(SubClassConstraint): +Thing_uri = URIRef(u'http://www.w3.org/2002/07/owl#Thing') + +class ComplementOfConstraint(SubClassConstraint): def narrow(self, domains): - subdom = domains[self.variable] - superdom = domains[self.object] + vals = domains[self.variable].getValues() + x_vals = domains[self.object].getValues() + for v in x_vals: + if v in vals: + raise ConsistencyFailure("%s cannot have the value %s and be \ + complementOf %s" % (v, self.object, self.variable)) + for v in domains['owl_Thing'].getValues(): + if not v in vals: + domains[self.variable].addValue(v) + class RangeConstraint(SubClassConstraint): @@ -285,7 +296,8 @@ elif self.variable in val.keys() and self.object in val.keys(): if not val[self.object] == val[self.variable]: raise ConsistencyFailure("Sameas failure: The two individuals (%s, %s) \ - has different values for property %r"%(self.variable, self.object, dom)) + has different values for property %r" % \ + (self.variable, self.object, dom)) else: if self.variable in vals and not self.object in vals: vals.append(self.object) Modified: pypy/dist/pypy/lib/pyontology/pyontology.py ============================================================================== --- pypy/dist/pypy/lib/pyontology/pyontology.py (original) +++ pypy/dist/pypy/lib/pyontology/pyontology.py Thu May 25 19:05:01 2006 @@ -4,8 +4,13 @@ from logilab.constraint.propagation import AbstractDomain, AbstractConstraint, ConsistencyFailure from constraint_classes import * import sys, py +from pypy.tool.ansi_print import ansi_log import time +log = py.log.Producer("Pyontology") +py.log.setconsumer("Pyontology", ansi_log) + + namespaces = { 'rdf' : 'http://www.w3.org/1999/02/22-rdf-syntax-ns', 'rdfs' : 'http://www.w3.org/2000/01/rdf-schema', @@ -56,7 +61,7 @@ self.values = {} self.setValues(values) self.name = name - self.properties = {} + self.property = None # The TBox is a dictionary containing terminology constraints # on predicates for this class. Keys are predicates, constraint # tupples ie. (p,'Carddinality') and values are list, comparison @@ -99,13 +104,16 @@ def setValues(self, values): self.values = dict.fromkeys(values) +class Thing(ClassDomain): + pass + class List(ClassDomain): def __init__(self, name='', values=[], bases = []): ClassDomain.__init__(self, name, values, bases) self.constraint = ListConstraint(name) -class Property(ClassDomain): +class Property(Thing): # Property contains the relationship between a class instance and a value # - a pair. To accomodate global assertions like 'range' and 'domain' attributes # for range and domain must be filled in by rdfs:range and rdfs:domain @@ -160,9 +168,6 @@ class DatatypeProperty(Property): pass -class Thing(ClassDomain): - pass - class DataRange(ClassDomain): pass @@ -181,12 +186,12 @@ def __init__(self, name='', values=[], bases = []): Property.__init__(self, name, values, bases) -# self.constraint = FunctionalCardinality(name) + self.constraint = FunctionalCardinality(name) def addValue(self, key, val): Property.addValue(self, key, val) - if len(self._dict[key]) > 1: - raise ConsistencyFailure("FunctionalProperties can only have one value") +# if len(self._dict[key]) > 1: +# raise ConsistencyFailure("FunctionalProperties can only have one value") class InverseFunctionalProperty(Property): @@ -293,20 +298,24 @@ self.graph.load(f, format=format) def attach_fd(self): - for (s, p, o) in (self.graph.triples((None,)*3)): - self.consider_triple((s, p, o)) + while len(list(self.graph.triples((None,)*3))) != len(self.seen.keys()): + for (s, p, o) in (self.graph.triples((None,)*3)): + self.consider_triple((s, p, o)) + log("=============================") assert len(list(self.graph.triples((None,)*3))) == len(self.seen.keys()) def consider_triple(self,(s, p, o)): + log("Trying %r" % ((s, p, o),)) if (s, p, o) in self.seen.keys(): return + log("Doing %r" % ((s, p, o),)) self.seen[(s, p, o)] = True if p.find('#') != -1: ns, func = p.split('#') else: ns ='' func = p - if ns in namespaces.values(): + if ns in namespaces.values() and hasattr(self, func): #predicate is one of builtin OWL or rdf predicates pred = getattr(self, func) res = pred(s, o) @@ -318,7 +327,7 @@ sub = self.make_var(Thing, s) obj = self.make_var(Thing, o) propdom = self.variables[avar] - res = propdom.addValue(sub, obj) + res = propdom.addValue(s, o) def resolve_item(self, item): item_as_subject = self.graph.triples((item, None, None)) @@ -336,6 +345,7 @@ self.consider_triple(triple) def make_var(self, cls=fd, a=''): + log("make_var %r,%r" %(cls,a)) if a in builtin_voc: cls = builtin_voc[a] if type(a) == URIRef: @@ -354,10 +364,14 @@ return var if not var in self.variables: self.variables[var] = cls(var) - elif type(self.variables[var]) in cls.__bases__: + # XXX needed because of old style classes + elif issubclass(cls, self.variables[var].__class__): vals = self.variables[var].getValues() - self.variables[var] = cls(var) - self.variables[var].setValues(vals) + tmp = cls(var) + tmp.setValues(vals) + tmp.property = self.variables[var].property + tmp.TBox = self.variables[var].TBox + self.variables[var] = tmp return var def evaluate(self, terms): @@ -425,10 +439,15 @@ def comment(self, s, var): pass + def label(self, s, var): + pass + def type(self, s, var): + log("type %r %r"%(s, var)) avar = self.make_var(ClassDomain, var) if not var in builtin_voc : - # var is not one of the builtin classes + # var is not one of the builtin classes -> it is a Thing + self.type(s, Thing_uri) svar = self.make_var(self.variables[avar].__class__, s) self.variables[avar].addValue(s) else: @@ -438,9 +457,9 @@ return else: svar = self.make_var(None, s) - if not (self.variables.has_key(svar) and - isinstance(self.variables[svar], cls)): - svar = self.make_var(cls, s) +# if not (self.variables.has_key(svar) and +# isinstance(self.variables[svar], cls)): + svar = self.make_var(cls, s) cls = self.variables[svar] if hasattr(cls, 'constraint'): self.constraints.append(cls.constraint) @@ -454,7 +473,8 @@ pass def onProperty(self, s, var): - self.resolve_predicate(var) +# self.resolve_predicate(var) + log("%r onProperty %r "%(s, var)) svar =self.make_var(Restriction, s) avar =self.make_var(Property, var) restr = self.variables[svar] @@ -468,13 +488,14 @@ # class extension of var, ie if a indiviual is in # the extension of s it must be in the extension of # var - self.resolve_item(s) + log("%r subClassOf %r "%(s, var)) self.resolve_item(var) +# self.resolve_item(s) avar = self.make_var(None, var) svar = self.make_var(ClassDomain, s) obj = self.variables[avar] sub = self.variables[svar] - +# assert (not isinstance(obj, Restriction)) or obj.TBox if obj.TBox: for key in obj.TBox.keys(): sub.TBox.setdefault(key,{}) @@ -483,9 +504,9 @@ prop.setdefault(typ, []) prop[typ].extend(obj.TBox[key][typ]) - if isinstance(self.variables[avar], Restriction): - self.variables[avar].TBox = {} - self.variables.pop(avar) +# if isinstance(self.variables[avar], Restriction): +# self.variables[avar].TBox = {} +# self.variables.pop(avar) else: cons = SubClassConstraint( svar, avar) self.constraints.append(cons) @@ -520,11 +541,11 @@ complementOf %s" % (s, v, var)) for v in self.variables[self.make_var(None,Thing_uri)].getValues(): if not v in vals: - self.variables[svar].addValue(v) + self.variables[svar].addValue(v) + self.constraints.append(ComplementOfConstraint(svar, avar)) def oneOf(self, s, var): var = self.flatten_rdf_list(var) -# print "*******", var, type(var), self.variables[var] #avar = self.make_var(List, var) svar = self.make_var(ClassDomain, s) res = self.variables[var].getValues() @@ -592,15 +613,14 @@ self.constraints.append(cons) def inverseOf(self, s, var): - self.resolve_item(s) - self.resolve_item(var) + self.resolve_predicate(s) + self.resolve_predicate(var) avar = self.make_var(Property, var) svar = self.make_var(Property, s) # con = InverseofConstraint(svar, avar) # self.constraints.append(con) avals = self.variables[avar].getValues() svals = self.variables[svar].getValues() - #import pdb;pdb.set_trace() for pair in avals: if not (pair[1], pair[0]) in svals: self.variables[svar].addValue(pair[1], pair[0]) @@ -613,36 +633,41 @@ def maxCardinality(self, s, var): """ Len of finite domain of the property shall be less than or equal to var""" self.resolve_item(s) + log("%r maxCardinality %r "%(s, var)) svar =self.make_var(Restriction, s) cls = list(self.graph.subjects(None,s))[0] self.resolve_item(cls) cls_name = self.make_var(ClassDomain, cls) prop = self.variables[svar].property + assert prop self.variables[svar].TBox[prop] = {'Cardinality': [( '<', int(var))]} - - self.constraints.append(CardinalityConstraint(prop, cls_name, var, '<=')) + self.constraints.append(CardinalityConstraint(prop, cls, var, '<=')) def minCardinality(self, s, var): """ Len of finite domain of the property shall be greater than or equal to var""" self.resolve_item(s) + log("%r minCardinality %r "%(s, var)) svar =self.make_var(Restriction, s) cls = list(self.graph.subjects(None,s))[0] cls_name = self.make_var(ClassDomain, cls) prop = self.variables[svar].property + assert prop self.variables[svar].TBox[prop] = {'Cardinality': [( '>', int(var))]} - self.constraints.append(CardinalityConstraint(prop, cls_name, var, '>=')) + self.constraints.append(CardinalityConstraint(prop, cls, var, '>=')) def cardinality(self, s, var): """ Len of finite domain of the property shall be equal to var""" self.resolve_item(s) + log("%r Cardinality %r "%(s, var)) svar =self.make_var(Restriction, s) cls = list(self.graph.subjects(None,s))[0] cls_name = self.make_var(ClassDomain, cls) prop = self.variables[svar].property + assert prop self.variables[svar].TBox[prop] = {'Cardinality': [( '=', int(var))]} - self.constraints.append(CardinalityConstraint(prop, cls_name, var, '==')) + self.constraints.append(CardinalityConstraint(prop, cls, var, '==')) def hasValue(self, s, var): self.resolve_item(s) @@ -677,8 +702,11 @@ avar = self.make_var(None, var) prop = self.variables[svar].property restr = self.variables[svar] - obj = self.variables[avar] - constrain_vals = set(obj.getValues()) + obj = self.variables.get(avar, None) + if obj: + constrain_vals = set(obj.getValues()) + else: + constrain_vals = set() restr.TBox[prop] = {'someValuesFrom' : [('someValuesFrom', avar)]} for cls,vals in self.variables[prop].getValuesPrKey(): if set(vals) & constrain_vals: @@ -708,14 +736,12 @@ constrain = DifferentfromConstraint(s_var, var_var) self.constraints.append(constrain) -#XXX need to change this def distinctMembers(self, s, var): s_var = self.make_var(AllDifferent, s) var_var = self.flatten_rdf_list(var) #var_var = self.make_var(List, var) - for v in var_var: - indx = var_var.index(v) - for other in var_var[indx+1:]: + diff_list = self.variables[var_var].getValues() + for v in diff_list: + indx = diff_list.index(v) + for other in diff_list[indx+1:]: self.differentFrom(v, other) - constrain = AllDifferentConstraint(s_var, var_var) - self.constraints.append(constrain) Modified: pypy/dist/pypy/lib/pyontology/test/test_ontology.py ============================================================================== --- pypy/dist/pypy/lib/pyontology/test/test_ontology.py (original) +++ pypy/dist/pypy/lib/pyontology/test/test_ontology.py Thu May 25 19:05:01 2006 @@ -122,7 +122,7 @@ O.make_var(ClassDomain, obj) O.type(sub, obj) - assert O.variables[O.make_var(None, sub)].__class__ == ClassDomain + assert O.variables[O.make_var(None, sub)].__class__ == Thing def test_ObjectProperty(): sub = URIRef('a') @@ -221,10 +221,10 @@ sub = URIRef('individ') obj = URIRef('c') O.type(sub, obj) - O.variables['p_'].setValues([('individ_',42)]) - #assert len(O.constraints) == 2 + O.variables['p_'].setValues([('individ',42)]) #add another valueof the property - py.test.raises(ConsistencyFailure, O.variables['p_'].setValues,[('individ_',42),('individ_',43)]) + O.variables['p_'].addValue('individ',43) + py.test.raises(ConsistencyFailure, O.consistency ) #check that consistency raises def test_inversefunctionalproperty(): @@ -294,7 +294,6 @@ assert ('Alice_', 'Bob_') in O.variables['friend_'].getValues() def test_inverseof(): - #py.test.skip("in transit") O = Ontology() own = URIRef('owner') obj = URIRef(namespaces['owl']+'#ObjectProperty') @@ -335,7 +334,7 @@ obj = URIRef(namespaces['owl']+'#Class') O.type(cls2, obj) O.subClassOf(cls2,restrict) - assert O.make_var(None, cls) in O.variables[O.make_var(None, cls2)].getValues() + assert cls in O.variables[O.make_var(None, cls2)].getValues() # py.test.raises(ConsistencyFailure, O.consistency) def test_List(): @@ -418,6 +417,7 @@ assert cls in O.variables[O.make_var(None, cls)].getValues() def test_unionof(): + py.test.skip("Rewrite the test") O = Ontology() cls = BNode('anon') own1 = BNode('liist1') @@ -435,6 +435,7 @@ assert res == ['1', '2', '3', '4', '5'] def test_intersectionof(): + py.test.skip("Rewrite the test") O = Ontology() cls = BNode('anon') O.intersectionOf(cls, [['1','2','3'],['3','4','5']]) @@ -496,7 +497,8 @@ py.test.raises(ConsistencyFailure, O.consistency) -def test_cardinality_terminology(): +def test_terminology_cardinality(): + py.test.skip("There is a bug in here somewhere") # Modeled after one of the standard tests (approved/maxCardinality) # 'cls' by subclassing two maxCardinality restrictions becomes the set of # individuals satisfying both restriction, ie having exactly 2 values of @@ -522,7 +524,8 @@ O.attach_fd() py.test.raises(ConsistencyFailure, O.check_TBoxes) -def test_subclassof_cardinality(): +def test_terminology_subclassof_cardinality(): + py.test.skip("There is a bug in here somewhere") cls = URIRef('cls') cls2 = URIRef('cls2') O = Ontology() @@ -608,3 +611,36 @@ O.type(URIRef('i5'), URIRef(namespaces['owl']+'#Thing')) O.type(URIRef('i4'), b_cls) raises(ConsistencyFailure, O.complementOf, b_cls, a_cls) + +def test_class_promotion(): + O = Ontology() + a_cls = URIRef('a') + O.type(a_cls, URIRef(namespaces['owl']+'#Class')) + + assert isinstance(O.variables['a_'], ClassDomain) + O.type(a_cls, URIRef(namespaces['owl']+'#Restriction')) + assert isinstance(O.variables['a_'], Restriction) + +def test_class_demotion(): + O = Ontology() + a_cls = URIRef('a') + O.type(a_cls, URIRef(namespaces['owl']+'#Restriction')) + O.variables[O.make_var(None, a_cls)].property = "SomeProp" + assert isinstance(O.variables['a_'], Restriction) + + O.type(a_cls, URIRef(namespaces['owl']+'#Class')) + + assert isinstance(O.variables['a_'], Restriction) + assert O.variables[O.make_var(None, a_cls)].property == "SomeProp" + +def test_thing_to_property(): + O = Ontology() + a_cls = URIRef('a') + O.type(a_cls, URIRef(namespaces['owl']+'#Thing')) + assert isinstance(O.variables['a_'], Thing) + O.type(a_cls, URIRef(namespaces['owl']+'#ObjectProperty')) + assert isinstance(O.variables['a_'], Property) + + O.type(a_cls, URIRef(namespaces['owl']+'#Thing')) + + assert isinstance(O.variables['a_'], Property) From tismer at codespeak.net Thu May 25 20:26:41 2006 From: tismer at codespeak.net (tismer at codespeak.net) Date: Thu, 25 May 2006 20:26:41 +0200 (CEST) Subject: [pypy-svn] r27681 - in pypy/dist/pypy/translator: c/test c/winproj/extension tool Message-ID: <20060525182641.A195910057@code0.codespeak.net> Author: tismer Date: Thu May 25 20:26:39 2006 New Revision: 27681 Modified: pypy/dist/pypy/translator/c/test/test_wrapping.py pypy/dist/pypy/translator/c/winproj/extension/extension.vcproj pypy/dist/pypy/translator/tool/raymond.py Log: enhanced heuristics for which method to automatically wrap and which not. The rule is: if a method is not special and starts with an underscore, we ignore it. Modified: pypy/dist/pypy/translator/c/test/test_wrapping.py ============================================================================== --- pypy/dist/pypy/translator/c/test/test_wrapping.py (original) +++ pypy/dist/pypy/translator/c/test/test_wrapping.py Thu May 25 20:26:39 2006 @@ -156,6 +156,7 @@ assert res == DemoClass(2, 3).demo() assert (obj + obj).demo() == 10 assert hasattr(m, '__init__') + assert m.zweiundvierzig == 42 if __name__=='__main__': test_expose_classes() Modified: pypy/dist/pypy/translator/c/winproj/extension/extension.vcproj ============================================================================== --- pypy/dist/pypy/translator/c/winproj/extension/extension.vcproj (original) +++ pypy/dist/pypy/translator/c/winproj/extension/extension.vcproj Thu May 25 20:26:39 2006 @@ -208,7 +208,7 @@ + RelativePath="F:\tmp\usession-502\testing_1\testing_1.c"> Modified: pypy/dist/pypy/translator/tool/raymond.py ============================================================================== --- pypy/dist/pypy/translator/tool/raymond.py (original) +++ pypy/dist/pypy/translator/tool/raymond.py Thu May 25 20:26:39 2006 @@ -30,6 +30,8 @@ if arity == 3 and '_set' in fname: ann[-1] = object SPECIAL_METHODS[fname] = ann + # __init__ is not in the table. + SPECIAL_METHODS['__init__'] = [None] setup_special_methods() def get_annotation(func, pre=[]): @@ -49,6 +51,11 @@ ret = [thetype or cls for thetype in pattern] return ret +def should_expose_method(func): + # expose all special methods but hide those starting with _ + name = func.__name__ + return name in SPECIAL_METHODS or not name.startswith('_') + def get_compiled_module(func, view=conftest.option.view, inline_threshold=1, use_boehm=False, exports=None): from pypy.translator.translator import TranslationContext @@ -78,9 +85,10 @@ rtyper.add_wrapper(clsdef) for obj in cls.__dict__.values(): if isinstance(obj, types.FunctionType): - if not ann.bookkeeper.getdesc(obj).querycallfamily(): - # not annotated, so enforce it - ann.build_types(obj, get_annotation(obj, [cls]), complete_now=False) + if should_expose_method(obj): + if not ann.bookkeeper.getdesc(obj).querycallfamily(): + # not annotated, so enforce it + ann.build_types(obj, get_annotation(obj, [cls]), complete_now=False) elif isinstance(obj, property): for obj in obj.fget, obj.fset, obj.fdel: if obj and not ann.bookkeeper.getdesc(obj).querycallfamily(): From tismer at codespeak.net Thu May 25 21:05:45 2006 From: tismer at codespeak.net (tismer at codespeak.net) Date: Thu, 25 May 2006 21:05:45 +0200 (CEST) Subject: [pypy-svn] r27687 - pypy/dist/pypy/translator/tool Message-ID: <20060525190545.078A410057@code0.codespeak.net> Author: tismer Date: Thu May 25 21:05:43 2006 New Revision: 27687 Modified: pypy/dist/pypy/translator/tool/raymond.py Log: new function get_bltn() which imports all CPython builtins once and initializes a global object with that Modified: pypy/dist/pypy/translator/tool/raymond.py ============================================================================== --- pypy/dist/pypy/translator/tool/raymond.py (original) +++ pypy/dist/pypy/translator/tool/raymond.py Thu May 25 21:05:43 2006 @@ -196,7 +196,7 @@ # the following would be much easier if we had # loop unrolling right inside the flowing process src = [] - src.append('def __init__(self):') + src.append('def _setup(self):') src.append(' import __builtin__ as b') import __builtin__ for name in dir(__builtin__): @@ -206,8 +206,17 @@ src = '\n'.join(src) #print src exec src + def __init__(self): + self._initialized = False del __builtin__, name, obj, src +bltn_singleton = BuiltinHelper() + +def get_bltn(): + if not bltn_singleton._initialized: + bltn_singleton._setup() + bltn_singleton._initialized = True + return bltn_singleton def get_methodname(funcidx): pass @@ -267,8 +276,7 @@ properties are re-created, too. """ import types - import __builtin__ as bltn - bltn = BuiltinHelper() + bltn = get_bltn() hasattr = bltn.hasattr isinstance = bltn.isinstance From ale at codespeak.net Fri May 26 11:09:51 2006 From: ale at codespeak.net (ale at codespeak.net) Date: Fri, 26 May 2006 11:09:51 +0200 (CEST) Subject: [pypy-svn] r27698 - pypy/dist/pypy/lib/pyontology Message-ID: <20060526090951.AB94710077@code0.codespeak.net> Author: ale Date: Fri May 26 11:09:50 2006 New Revision: 27698 Modified: pypy/dist/pypy/lib/pyontology/pyontology.py Log: Simplification Modified: pypy/dist/pypy/lib/pyontology/pyontology.py ============================================================================== --- pypy/dist/pypy/lib/pyontology/pyontology.py (original) +++ pypy/dist/pypy/lib/pyontology/pyontology.py Fri May 26 11:09:50 2006 @@ -630,44 +630,30 @@ #---Property restrictions------------------------------------------------------ - def maxCardinality(self, s, var): - """ Len of finite domain of the property shall be less than or equal to var""" + def cardinality_helper(self, s, var, card): self.resolve_item(s) - log("%r maxCardinality %r "%(s, var)) + log("%r %sCardinality %r "%(s, card, var)) svar =self.make_var(Restriction, s) cls = list(self.graph.subjects(None,s))[0] self.resolve_item(cls) cls_name = self.make_var(ClassDomain, cls) prop = self.variables[svar].property assert prop - self.variables[svar].TBox[prop] = {'Cardinality': [( '<', int(var))]} - self.constraints.append(CardinalityConstraint(prop, cls, var, '<=')) + comp = {'max': '<', 'min': '>'}.get(card, '=') + self.variables[svar].TBox[prop] = {'Cardinality': [( comp, int(var))]} + self.constraints.append(CardinalityConstraint(prop, cls, var, comp+'=')) + def maxCardinality(self, s, var): + """ Len of finite domain of the property shall be less than or equal to var""" + self.cardinality_helper(s, var, 'max') + def minCardinality(self, s, var): """ Len of finite domain of the property shall be greater than or equal to var""" - self.resolve_item(s) - log("%r minCardinality %r "%(s, var)) - svar =self.make_var(Restriction, s) - cls = list(self.graph.subjects(None,s))[0] - cls_name = self.make_var(ClassDomain, cls) - prop = self.variables[svar].property - assert prop - self.variables[svar].TBox[prop] = {'Cardinality': [( '>', int(var))]} - - self.constraints.append(CardinalityConstraint(prop, cls, var, '>=')) + self.cardinality_helper(s, var, 'min') def cardinality(self, s, var): """ Len of finite domain of the property shall be equal to var""" - self.resolve_item(s) - log("%r Cardinality %r "%(s, var)) - svar =self.make_var(Restriction, s) - cls = list(self.graph.subjects(None,s))[0] - cls_name = self.make_var(ClassDomain, cls) - prop = self.variables[svar].property - assert prop - self.variables[svar].TBox[prop] = {'Cardinality': [( '=', int(var))]} - - self.constraints.append(CardinalityConstraint(prop, cls, var, '==')) + self.cardinality_helper(s, var, '') def hasValue(self, s, var): self.resolve_item(s) @@ -729,7 +715,6 @@ constrain = SameasConstraint(s_var, var_var) self.constraints.append(constrain) - def differentFrom(self, s, var): s_var = self.make_var(Thing, s) var_var = self.make_var(Thing, var) From ale at codespeak.net Fri May 26 11:36:18 2006 From: ale at codespeak.net (ale at codespeak.net) Date: Fri, 26 May 2006 11:36:18 +0200 (CEST) Subject: [pypy-svn] r27701 - in pypy/dist/pypy/lib/pyontology: . test Message-ID: <20060526093618.3E7A410079@code0.codespeak.net> Author: ale Date: Fri May 26 11:36:10 2006 New Revision: 27701 Modified: pypy/dist/pypy/lib/pyontology/constraint_classes.py pypy/dist/pypy/lib/pyontology/pyontology.py pypy/dist/pypy/lib/pyontology/test/test_ontology.py Log: Found the bug I think Modified: pypy/dist/pypy/lib/pyontology/constraint_classes.py ============================================================================== --- pypy/dist/pypy/lib/pyontology/constraint_classes.py (original) +++ pypy/dist/pypy/lib/pyontology/constraint_classes.py Fri May 26 11:36:10 2006 @@ -28,10 +28,10 @@ cost = 10 - def __init__(self, prop, cls_name, var, comp): + def __init__(self, prop, var, comp): AbstractConstraint.__init__(self, [prop]) self.check_individual = "domains['%s'].getValues() != []" % prop - self.formula = "len(domains['%s'].getValuesPrKey('%s')) %s int(%s)"% (prop, cls_name, comp, var) + self.formula = "len(domains['%s'].getValuesPrKey('%s')) %s int(%s)"% (prop, var, comp, var) def estimateCost(self, domains): return self.cost Modified: pypy/dist/pypy/lib/pyontology/pyontology.py ============================================================================== --- pypy/dist/pypy/lib/pyontology/pyontology.py (original) +++ pypy/dist/pypy/lib/pyontology/pyontology.py Fri May 26 11:36:10 2006 @@ -634,14 +634,11 @@ self.resolve_item(s) log("%r %sCardinality %r "%(s, card, var)) svar =self.make_var(Restriction, s) - cls = list(self.graph.subjects(None,s))[0] - self.resolve_item(cls) - cls_name = self.make_var(ClassDomain, cls) prop = self.variables[svar].property assert prop comp = {'max': '<', 'min': '>'}.get(card, '=') self.variables[svar].TBox[prop] = {'Cardinality': [( comp, int(var))]} - self.constraints.append(CardinalityConstraint(prop, cls, var, comp+'=')) + self.constraints.append(CardinalityConstraint(prop, var, comp+'=')) def maxCardinality(self, s, var): """ Len of finite domain of the property shall be less than or equal to var""" Modified: pypy/dist/pypy/lib/pyontology/test/test_ontology.py ============================================================================== --- pypy/dist/pypy/lib/pyontology/test/test_ontology.py (original) +++ pypy/dist/pypy/lib/pyontology/test/test_ontology.py Fri May 26 11:36:10 2006 @@ -498,7 +498,6 @@ def test_terminology_cardinality(): - py.test.skip("There is a bug in here somewhere") # Modeled after one of the standard tests (approved/maxCardinality) # 'cls' by subclassing two maxCardinality restrictions becomes the set of # individuals satisfying both restriction, ie having exactly 2 values of @@ -525,7 +524,6 @@ py.test.raises(ConsistencyFailure, O.check_TBoxes) def test_terminology_subclassof_cardinality(): - py.test.skip("There is a bug in here somewhere") cls = URIRef('cls') cls2 = URIRef('cls2') O = Ontology() From antocuni at codespeak.net Fri May 26 14:20:36 2006 From: antocuni at codespeak.net (antocuni at codespeak.net) Date: Fri, 26 May 2006 14:20:36 +0200 (CEST) Subject: [pypy-svn] r27725 - in pypy/dist/pypy/rpython: ootypesystem test Message-ID: <20060526122036.3B2E110077@code0.codespeak.net> Author: antocuni Date: Fri May 26 14:20:29 2006 New Revision: 27725 Modified: pypy/dist/pypy/rpython/ootypesystem/rlist.py pypy/dist/pypy/rpython/test/test_rdict.py pypy/dist/pypy/rpython/test/test_rlist.py Log: Don't use separate internal and external item repr for ootypesystem list, because high level backends don't need it. Modified: pypy/dist/pypy/rpython/ootypesystem/rlist.py ============================================================================== --- pypy/dist/pypy/rpython/ootypesystem/rlist.py (original) +++ pypy/dist/pypy/rpython/ootypesystem/rlist.py Fri May 26 14:20:29 2006 @@ -26,10 +26,16 @@ self.list_cache = {} # setup() needs to be called to finish this initialization + def _externalvsinternal(self, rtyper, item_repr): + # EXPERIMENTAL: distinct internal and external repr are not + # needed in high level backends + #return externalvsinternal(rtyper, item_repr) + return item_repr, item_repr + def _setup_repr(self): if 'item_repr' not in self.__dict__: self.external_item_repr, self.item_repr = \ - externalvsinternal(self.rtyper, self._item_repr_computer()) + self._externalvsinternal(self.rtyper, self._item_repr_computer()) if not ootype.hasItemType(self.lowleveltype): ootype.setItemType(self.lowleveltype, self.item_repr.lowleveltype) 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 May 26 14:20:29 2006 @@ -460,7 +460,6 @@ assert res == f(2) def test_dict_of_dict(self): - self._skip_oo('dict of dict') def f(n): d = {} d[5] = d 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 May 26 14:20:29 2006 @@ -1040,6 +1040,7 @@ assert res == 2 def test_type_erase_fixed_size(self): + self._skip_oo('type erasing') class A(object): pass class B(object): @@ -1064,6 +1065,7 @@ assert r_A_list.lowleveltype == r_B_list.lowleveltype def test_type_erase_var_size(self): + self._skip_oo('type erasing') class A(object): pass class B(object): From antocuni at codespeak.net Fri May 26 17:11:22 2006 From: antocuni at codespeak.net (antocuni at codespeak.net) Date: Fri, 26 May 2006 17:11:22 +0200 (CEST) Subject: [pypy-svn] r27729 - in pypy/dist/pypy/translator/cli: . src test Message-ID: <20060526151122.92D251008E@code0.codespeak.net> Author: antocuni Date: Fri May 26 17:11:07 2006 New Revision: 27729 Added: pypy/dist/pypy/translator/cli/test/test_constant.py (contents, props changed) Modified: pypy/dist/pypy/translator/cli/class_.py pypy/dist/pypy/translator/cli/database.py pypy/dist/pypy/translator/cli/function.py pypy/dist/pypy/translator/cli/oopspec.py pypy/dist/pypy/translator/cli/opcodes.py pypy/dist/pypy/translator/cli/src/pypylib.cs pypy/dist/pypy/translator/cli/test/runtest.py pypy/dist/pypy/translator/cli/test/test_list.py pypy/dist/pypy/translator/cli/test/test_oo.py Log: - Added support for list and char constants. - Added support for returning lists and instances in CliTest.interpret. - Fixed two bugs in oonull and bool_not. - Use CliTest for taking advantage of tests from rpython/test/test_rlist.py. Modified: pypy/dist/pypy/translator/cli/class_.py ============================================================================== --- pypy/dist/pypy/translator/cli/class_.py (original) +++ pypy/dist/pypy/translator/cli/class_.py Fri May 26 17:11:07 2006 @@ -50,6 +50,7 @@ # TODO: should the .ctor set the default values? self._ctor() + self._toString() # lazy import to avoid circular dependencies #import pypy.translator.cli.function as function @@ -71,3 +72,11 @@ self.ilasm.call('instance void %s::.ctor()' % self.get_base_class()) self.ilasm.opcode('ret') self.ilasm.end_function() + + def _toString(self): + self.ilasm.begin_function('ToString', [], 'string', False, 'virtual', 'instance', 'default') + self.ilasm.opcode('ldarg.0') + self.ilasm.call('string class [pypylib]pypy.test.Result::ToPython(object)') + self.ilasm.ret() + self.ilasm.end_function() + Modified: pypy/dist/pypy/translator/cli/database.py ============================================================================== --- pypy/dist/pypy/translator/cli/database.py (original) +++ pypy/dist/pypy/translator/cli/database.py Fri May 26 17:11:07 2006 @@ -3,6 +3,7 @@ from pypy.translator.cli.class_ import Class from pypy.translator.cli.record import Record from pypy.rpython.ootypesystem import ootype +from pypy.rpython.lltypesystem import lltype from pypy.translator.cli.opcodes import opcodes try: @@ -73,17 +74,42 @@ ilasm.begin_namespace(CONST_NAMESPACE) ilasm.begin_class(CONST_CLASS) - # render field definitions - for const, name in self.consts.iteritems(): - ilasm.field(name, const.get_type(), static=True) - # initialize fields + + # This strange machinery it's necessary because it could be + # happen that new constants are registered during rendering of + # constants. So we split initialization of constants in a + # number of 'steps' that are executed in reverse order as they + # are rendered. The first step to be executed will be stepN, + # the last step0. + + step = 0 + while self.consts: + consts = self.consts + self.consts = {} + + # render field definitions + for const, name in consts.iteritems(): + ilasm.field(name, const.get_type(), static=True) + + ilasm.begin_function('step%d' % step, [], 'void', False, 'static') + for const, name in consts.iteritems(): + const.init(ilasm) + type_ = const.get_type() + ilasm.set_static_field (type_, CONST_NAMESPACE, CONST_CLASS, name) + + ilasm.ret() + ilasm.end_function() + step += 1 + + # the constructor calls the steps in reverse order ilasm.begin_function('.cctor', [], 'void', False, 'static', 'specialname', 'rtspecialname', 'default') - for const, name in self.consts.iteritems(): - const.init(ilasm) - type_ = const.get_type() - ilasm.set_static_field (type_, CONST_NAMESPACE, CONST_CLASS, name) + + last_step = step-1 + for step in xrange(last_step, -1, -1): + func = '%s.%s::%s' % (CONST_NAMESPACE, CONST_CLASS, 'step%d' % step) + ilasm.call('void %s()' % func) ilasm.ret() ilasm.end_function() @@ -104,21 +130,24 @@ return InstanceConst(db, const, static_type) elif isinstance(const, ootype._record): return RecordConst(db, const) + elif isinstance(const, ootype._list): + return ListConst(db, const) else: assert False, 'Unknown constant: %s' % const make = staticmethod(make) def load(db, TYPE, value, ilasm): - # TODO: code duplicated from function.py, refactoring needed if TYPE is ootype.Void: pass elif TYPE is ootype.Bool: ilasm.opcode('ldc.i4', str(int(value))) + elif TYPE is ootype.Char: + ilasm.opcode('ldc.i4', ord(value)) elif TYPE is ootype.Float: ilasm.opcode('ldc.r8', repr(value)) elif TYPE in (ootype.Signed, ootype.Unsigned): ilasm.opcode('ldc.i4', str(value)) - elif TYPE in (ootype.SignedLongLong, ootype.UnsignedLongLong): + elif TYPE in (lltype.SignedLongLong, lltype.UnsignedLongLong): ilasm.opcode('ldc.i8', str(value)) else: cts = CTS(db) @@ -151,11 +180,11 @@ def get_name(self): return 'Record' - def get_type(self): - return self.cts.lltype_to_cts(self.record._TYPE) + def get_type(self, include_class=True): + return self.cts.lltype_to_cts(self.record._TYPE, include_class) def init(self, ilasm): - class_name = self.record._TYPE._name + class_name = self.get_type(False) ilasm.new('instance void class %s::.ctor()' % class_name) for f_name, (FIELD_TYPE, f_default) in self.record._TYPE._fields.iteritems(): f_type = self.cts.lltype_to_cts(FIELD_TYPE) @@ -164,6 +193,49 @@ AbstractConst.load(self.db, FIELD_TYPE, value, ilasm) ilasm.set_field((f_type, class_name, f_name)) +class ListConst(AbstractConst): + def __init__(self, db, list_): + self.db = db + self.cts = CTS(db) + self.list = list_ + + def __hash__(self): + return hash(self.list) + + def __eq__(self, other): + return self.list == other.list + + def get_name(self): + return 'List' + + def get_type(self, include_class=True): + return self.cts.lltype_to_cts(self.list._TYPE, include_class) + + def init(self, ilasm): + if not self.list: # it is a null list + ilasm.opcode('ldnull') + return + + class_name = self.get_type(False) + ITEMTYPE = self.list._TYPE._ITEMTYPE + itemtype = self.cts.lltype_to_cts(ITEMTYPE) + itemtype_T = self.cts.lltype_to_cts(self.list._TYPE.ITEMTYPE_T) + ilasm.new('instance void class %s::.ctor()' % class_name) + + # special case: List(Void); only resize it, don't care of the contents + if ITEMTYPE is ootype.Void: + ilasm.opcode('dup') + AbstractConst.load(self.db, ootype.Signed, len(self.list._list), ilasm) + meth = 'void class [pypylib]pypy.runtime.List`1::_ll_resize(int32)' + ilasm.call_method(meth, False) + return + + for item in self.list._list: + ilasm.opcode('dup') + AbstractConst.load(self.db, ITEMTYPE, item, ilasm) + meth = 'void class [pypylib]pypy.runtime.List`1<%s>::Add(%s)' % (itemtype, itemtype_T) + ilasm.call_method(meth, False) + class InstanceConst(AbstractConst): def __init__(self, db, obj, static_type): self.cts = CTS(db) Modified: pypy/dist/pypy/translator/cli/function.py ============================================================================== --- pypy/dist/pypy/translator/cli/function.py (original) +++ pypy/dist/pypy/translator/cli/function.py Fri May 26 17:11:07 2006 @@ -297,24 +297,9 @@ else: assert False - def _load_const(self, const): - type_ = const.concretetype - if type_ is Void: - pass - elif type_ is Bool: - self.ilasm.opcode('ldc.i4', str(int(const.value))) - elif type_ is Float: - self.ilasm.opcode('ldc.r8', repr(const.value)) - elif type_ in (Signed, Unsigned): - self.ilasm.opcode('ldc.i4', str(const.value)) - elif type_ in (SignedLongLong, UnsignedLongLong): - self.ilasm.opcode('ldc.i8', str(const.value)) - else: - name = self.db.record_const(const.value) - cts_type = self.cts.lltype_to_cts(type_) - self.ilasm.opcode('ldsfld %s %s' % (cts_type, name)) - #assert False, 'Unknown constant %s' % const - + def _load_const(self, const): + from pypy.translator.cli.database import AbstractConst + AbstractConst.load(self.db, const.concretetype, const.value, self.ilasm) def store(self, v): if isinstance(v, flowmodel.Variable): Modified: pypy/dist/pypy/translator/cli/oopspec.py ============================================================================== --- pypy/dist/pypy/translator/cli/oopspec.py (original) +++ pypy/dist/pypy/translator/cli/oopspec.py Fri May 26 17:11:07 2006 @@ -10,7 +10,10 @@ # builtin methods take the same arguments of the corresponding # ll_* function. full_name, _ = oopspec.split('(', 1) - type_name, method_name = full_name.split('.') + try: + type_name, method_name = full_name.split('.') + except ValueError: + return None try: type_ = BUILTIN_TYPES[type_name] Modified: pypy/dist/pypy/translator/cli/opcodes.py ============================================================================== --- pypy/dist/pypy/translator/cli/opcodes.py (original) +++ pypy/dist/pypy/translator/cli/opcodes.py Fri May 26 17:11:07 2006 @@ -45,7 +45,7 @@ 'ooupcast': DoNothing, 'oodowncast': DoNothing, # TODO: is it really safe? 'oois': 'ceq', - + 'oononnull': [PushAllArgs, 'ldnull', 'ceq']+Not, 'same_as': DoNothing, # TODO: does same_as really do nothing else than renaming? 'direct_call': [Call], @@ -53,7 +53,7 @@ # __________ numeric operations __________ - 'bool_not': Not, + 'bool_not': [PushAllArgs]+Not, 'char_lt': None, 'char_le': None, Modified: pypy/dist/pypy/translator/cli/src/pypylib.cs ============================================================================== --- pypy/dist/pypy/translator/cli/src/pypylib.cs (original) +++ pypy/dist/pypy/translator/cli/src/pypylib.cs Fri May 26 17:11:07 2006 @@ -9,6 +9,11 @@ public static string ToPython(bool x) { return x.ToString(); } public static string ToPython(double x) { return x.ToString(); } public static string ToPython(char x) { return string.Format("'{0}'", x); } + + public static string ToPython(object obj) + { + return string.Format("InstanceWrapper('{0}')", obj.GetType().FullName); + } } } Modified: pypy/dist/pypy/translator/cli/test/runtest.py ============================================================================== --- pypy/dist/pypy/translator/cli/test/runtest.py (original) +++ pypy/dist/pypy/translator/cli/test/runtest.py Fri May 26 17:11:07 2006 @@ -34,12 +34,14 @@ assert res1 == res2 def format_object(TYPE, ilasm): - if isinstance(TYPE, ootype.BuiltinType): + if isinstance(TYPE, (ootype.BuiltinType, ootype.Instance)): ilasm.call_method('string object::ToString()', virtual=True) + elif TYPE is ootype.Void: + ilasm.opcode('ldstr "None"') else: type_ = cts.lltype_to_cts(TYPE) ilasm.call('string class [pypylib]pypy.test.Result::ToPython(%s)' % type_) - + class TestEntryPoint(Node): """ @@ -158,6 +160,8 @@ res = eval(stdout) if isinstance(res, tuple): res = StructTuple(res) # so tests can access tuple elements with .item0, .item1, etc. + elif isinstance(res, list): + res = OOList(res) return res class StructTuple(tuple): @@ -168,13 +172,24 @@ else: raise AttributeError, name +class OOList(list): + def ll_length(self): + return len(self) + + def ll_getitem_fast(self, i): + return self[i] + +class InstanceWrapper: + def __init__(self, class_name): + self.class_name = class_name + class CliTest(BaseRtypingTest, OORtypeMixin): def interpret(self, fn, args): ann = [lltype_to_annotation(typeOf(x)) for x in args] f = compile_function(fn, ann) return f(*args) - def interpret_raises(exc, func, args): + def interpret_raises(self, exc, func, args): py.test.skip("CLI tests don't support interpret_raises") def ll_to_string(self, s): @@ -184,4 +199,4 @@ return l def class_name(self, value): - py.test.skip('class_name not supported, yet') + return value.class_name.split(".")[-1] Added: pypy/dist/pypy/translator/cli/test/test_constant.py ============================================================================== --- (empty file) +++ pypy/dist/pypy/translator/cli/test/test_constant.py Fri May 26 17:11:07 2006 @@ -0,0 +1,55 @@ +from pypy.translator.cli.test.runtest import CliTest + +# used in tests below +class A: + pass + + +class TestConstant(CliTest): + def test_char(self): + const = 'a' + def fn(): + return const + assert self.interpret(fn, []) == 'a' + + def test_void(self): + def fn(): + pass + assert self.interpret(fn, []) is None + + def test_tuple(self): + const = 1, 2 + def fn(): + return const + res = self.interpret(fn, []) + assert res.item0 == 1 + assert res.item1 == 2 + + def test_list(self): + const = [1, 2] + def fn(): + return const + res = self.ll_to_list(self.interpret(fn, [])) + assert res == [1, 2] + + def test_compound_const(self): + const = ([1, 2], [3, 4]) + def fn(): + return const + res = self.interpret(fn, []) + assert self.ll_to_list(res.item0) == [1, 2] + assert self.ll_to_list(res.item1) == [3, 4] + + def test_instance(self): + const = A() + def fn(): + return const + res = self.interpret(fn, []) + assert self.class_name(res) == 'A' + + def test_list_of_instances(self): + const = [A()] + def fn(): + return const + res = self.ll_to_list(self.interpret(fn, [])) + assert self.class_name(res[0]) == 'A' Modified: pypy/dist/pypy/translator/cli/test/test_list.py ============================================================================== --- pypy/dist/pypy/translator/cli/test/test_list.py (original) +++ pypy/dist/pypy/translator/cli/test/test_list.py Fri May 26 17:11:07 2006 @@ -1,91 +1,20 @@ -from pypy.translator.cli.test.runtest import check +import py -def test_list(): - for name, func in globals().iteritems(): - if not name.startswith('list_'): - continue +from pypy.translator.cli.test.runtest import CliTest +from pypy.rpython.test.test_rlist import BaseTestRlist - yield check, func, [int, int], (42, 13) +class TestCliList(CliTest, BaseTestRlist): + def test_recursive(self): + py.test.skip("CLI doesn't support recursive lists") + + def test_list_comparestr(self): + py.test.skip("CLI doesn't support string, yet") + + def test_not_a_char_list_after_all(self): + py.test.skip("CLI doesn't support string, yet") + + def test_list_str(self): + py.test.skip("CLI doesn't support string, yet") - -def create(x, y): - return [1, 2, 3, x, y, x+y, x*y] - -def sum_(lst): - total = 0 - i = 0 - while i < len(lst): - total += lst[i] - i += 1 - - return total - -def list_sum(x, y): - return sum_(create(x, y)) - -def list_append(x, y): - lst = create(x, y) - lst.append(x) - return sum_(lst) - -def list_setitem(x, y): - lst = create(x, y) - lst[0] = 0 - lst[1] = 0 - return sum_(lst) - -def list_iteration(x, y): - lst = create(x, y) - total = 1 - for item in lst: - total *= item - return total - -def list_concat(x, y): - lst1 = create(x, x) - lst2 = create(y, y) - return sum_(lst1 + lst2) - -def list_extend(x, y): - lst = create(x, y) - lst += [y, y*2] - lst.extend([x, y]) - return sum_(lst) - -def list_negative_index(x, y): - lst = create(x, y) - lst[-1] = 4321 - lst[-2] = lst[-1] - return sum_(lst) - -def list_getslice(x, y): - lst = create(x, y) - return sum_(lst[1:3]) * sum_(lst[3:]) * sum_(lst[:-1]) - -def list_setslice(x, y): - lst = create(x, y) - lst[1:3] = [1234, 5678] - return sum_(lst) - -def list_bltn_list(x, y): - lst = create(x, y) - lst2 = list(lst) - del lst2[:] - return sum_(lst) - -def list_del_item_slice(x, y): - lst = create(x, y) - del lst[0] - del lst[2:4] - del lst[5:] - return sum_(lst) - -def list_index(x, y): - lst = create(x, y) - res = lst.index(x) - try: - lst.index(x*y+1) - except ValueError: - res += 1 - - return res + def test_inst_list(self): + py.test.skip("CLI doesn't support string, yet") Modified: pypy/dist/pypy/translator/cli/test/test_oo.py ============================================================================== --- pypy/dist/pypy/translator/cli/test/test_oo.py (original) +++ pypy/dist/pypy/translator/cli/test/test_oo.py Fri May 26 17:11:07 2006 @@ -25,10 +25,6 @@ return x*y static_meth = staticmethod(static_meth) -## def class_meth(cls, x, y): -## return x*y + cls.INCREMENT -## class_meth = classmethod(class_meth) - def class_attribute(self): return self.x + self.INCREMENT @@ -80,8 +76,14 @@ def oo_runtimenew(x, y): return init_and_compute(MyClass, x, y) + init_and_compute(MyDerivedClass, x, y) -##def oo_class_meth(x, y): -## return MyClass.class_meth(x, y) + MyDerivedClass.class_meth(x, y) +def nonnull_helper(lst): + if lst is None: + return 1 + else: + return 2 + +def oo_nonnull(x, y): + return nonnull_helper([]) + nonnull_helper(None) if __name__ == '__main__': from pypy.translator.cli import conftest From ac at codespeak.net Fri May 26 17:31:49 2006 From: ac at codespeak.net (ac at codespeak.net) Date: Fri, 26 May 2006 17:31:49 +0200 (CEST) Subject: [pypy-svn] r27730 - pypy/extradoc/sprintinfo/ddorf2006 Message-ID: <20060526153149.CD76810091@code0.codespeak.net> Author: ac Date: Fri May 26 17:31:44 2006 New Revision: 27730 Modified: pypy/extradoc/sprintinfo/ddorf2006/people.txt Log: We found a place to stay Modified: pypy/extradoc/sprintinfo/ddorf2006/people.txt ============================================================================== --- pypy/extradoc/sprintinfo/ddorf2006/people.txt (original) +++ pypy/extradoc/sprintinfo/ddorf2006/people.txt Fri May 26 17:31:44 2006 @@ -14,8 +14,8 @@ Carl Friedrich Bolz nope :-) private Eric van Riet Paap 6th - 8th private Maciej Fijalkowski 3rd-9th cfbolz -Anders Chrigstroem 1st - 9th ? -Samuele Pedroni 1st - 9th ? +Anders Chrigstroem 1st - 9th Hotel an der Uni +Samuele Pedroni 1st - 9th Hotel an der Uni Christian Tismer 1st - 9th ? Antonio Cuni 1st - 9th cfbolz Anders Lehmann 2nd - 9th ? From antocuni at codespeak.net Fri May 26 19:13:18 2006 From: antocuni at codespeak.net (antocuni at codespeak.net) Date: Fri, 26 May 2006 19:13:18 +0200 (CEST) Subject: [pypy-svn] r27735 - in pypy/dist/pypy/translator/cli: src test Message-ID: <20060526171318.49B3410088@code0.codespeak.net> Author: antocuni Date: Fri May 26 19:13:07 2006 New Revision: 27735 Modified: pypy/dist/pypy/translator/cli/src/pypylib.cs pypy/dist/pypy/translator/cli/test/runtest.py pypy/dist/pypy/translator/cli/test/test_runtest.py Log: Added support for CliTest.interpret_raises. Modified: pypy/dist/pypy/translator/cli/src/pypylib.cs ============================================================================== --- pypy/dist/pypy/translator/cli/src/pypylib.cs (original) +++ pypy/dist/pypy/translator/cli/src/pypylib.cs Fri May 26 19:13:07 2006 @@ -14,6 +14,11 @@ { return string.Format("InstanceWrapper('{0}')", obj.GetType().FullName); } + + public static string FormatException(object obj) + { + return string.Format("ExceptionWrapper('{0}')", obj.GetType().FullName); + } } } Modified: pypy/dist/pypy/translator/cli/test/runtest.py ============================================================================== --- pypy/dist/pypy/translator/cli/test/runtest.py (original) +++ pypy/dist/pypy/translator/cli/test/runtest.py Fri May 26 19:13:07 2006 @@ -68,12 +68,24 @@ ilasm.call('%s class [mscorlib]System.Convert::%s(string)' % (arg_type, self.__convert_method(arg_type))) + # call the function and convert the result to a string containing a valid python expression + ilasm.begin_try() ilasm.call(cts.graph_to_signature(self.graph)) - - # convert result to a string containing a valid python expression TYPE = self.graph.getreturnvar().concretetype format_object(TYPE, ilasm) ilasm.call('void class [mscorlib]System.Console::WriteLine(string)') + ilasm.leave('return') + ilasm.end_try() + + for exc in ('[mscorlib]System.Exception', 'exceptions.Exception'): + ilasm.begin_catch(exc) + ilasm.call('string class [pypylib]pypy.test.Result::FormatException(object)') + ilasm.call('void class [mscorlib]System.Console::WriteLine(string)') + ilasm.leave('return') + ilasm.end_catch() + + # write the result to stdout + ilasm.label('return') ilasm.opcode('ret') ilasm.end_function() self.db.pending_function(self.graph) @@ -157,6 +169,7 @@ retval = mono.wait() assert retval == 0, stderr + print stdout res = eval(stdout) if isinstance(res, tuple): res = StructTuple(res) # so tests can access tuple elements with .item0, .item1, etc. @@ -183,14 +196,22 @@ def __init__(self, class_name): self.class_name = class_name +class ExceptionWrapper: + def __init__(self, class_name): + self.class_name = class_name + + class CliTest(BaseRtypingTest, OORtypeMixin): def interpret(self, fn, args): ann = [lltype_to_annotation(typeOf(x)) for x in args] f = compile_function(fn, ann) return f(*args) - def interpret_raises(self, exc, func, args): - py.test.skip("CLI tests don't support interpret_raises") + def interpret_raises(self, exception, fn, args): + import exceptions # needed by eval + res = self.interpret(fn, args) + assert isinstance(res, ExceptionWrapper) + assert eval(res.class_name) is exception def ll_to_string(self, s): py.test.skip('ll_to_string not supported, yet') Modified: pypy/dist/pypy/translator/cli/test/test_runtest.py ============================================================================== --- pypy/dist/pypy/translator/cli/test/test_runtest.py (original) +++ pypy/dist/pypy/translator/cli/test/test_runtest.py Fri May 26 19:13:07 2006 @@ -30,3 +30,8 @@ def fn(): return 1, 2 assert self.interpret(fn, []) == (1, 2) + + def test_exception(self): + def fn(): + raise ValueError + self.interpret_raises(ValueError, fn, []) From arigo at codespeak.net Fri May 26 21:02:33 2006 From: arigo at codespeak.net (arigo at codespeak.net) Date: Fri, 26 May 2006 21:02:33 +0200 (CEST) Subject: [pypy-svn] r27740 - pypy/extradoc/talk/dls2006 Message-ID: <20060526190233.ED15810098@code0.codespeak.net> Author: arigo Date: Fri May 26 21:02:32 2006 New Revision: 27740 Modified: pypy/extradoc/talk/dls2006/draft.txt Log: Drafted section 3. Dinner time now :-) Modified: pypy/extradoc/talk/dls2006/draft.txt ============================================================================== --- pypy/extradoc/talk/dls2006/draft.txt (original) +++ pypy/extradoc/talk/dls2006/draft.txt Fri May 26 21:02:32 2006 @@ -63,35 +63,19 @@ PyPy achieves this goal without giving up on the efficiency of the compiled VMs. -The key factors enabling this result are not to be found -in recent advances in any particular research area - we are not using -any sophisticated GC, any constraint-based type inference, any advanced -meta-programmingconcepts. -[this claim formulated this way is confusing, the GC aspect is marginal -and we could adopt a sophisticated GC, the constraint based type inference -is pertinent, but the meta-programming is a bit too vague, -there's no accepted definition of what should be considered advanced meta-programming, and what we do is meta-programming for some definition, -I would just cite the constraint type inference as example, and be happy] - -Instead, we are following a novel overall architecture: it is split -into many levels of stepwise translation from the high-level source of -the VM to the final target platform. Similar platforms can reuse many -of these steps, while for very different platforms we have the option -to perform very different translation steps. Each step reuses a -common type inference component, but with a different type -system. Steps are based on flow graph transformation and rewriting and -by augmenting the program with further implementation code written in -Python and analysed with the suitable type system. For the various -analyses used, not only type inference, we try to formulate them as -abstract interpretation, mitigating the potential efficiency problem -by wise choices and compromises for the domain used, but gaining much -more freedom and controllability without needing to think -sophisticated setup transformations to prepare the input for more -tailored algorithms. +The key factors enabling this result are not to be found in recent +advances in any particular research area - we are not for example using +constraint-based type inference. Instead, we are following a novel +overall architecture: it is split into many levels of stepwise +translation from the high-level source of the VM to the final target +platform. Similar platforms can reuse many of these steps, while for +very different platforms we have the option to perform very different +translation steps. Each step reuses a common type inference component +with a different, ad-hoc type system. Experiments also suggest a more mundane reason why such an approach is only practical today: a typical translation takes about half an hour -on a modern PC and consumes close to 1GB of RAM. +on a modern PC and consumes between 512MB and 1GB of RAM. We shortly describe the architecture of PyPy in `section 2`_. In `section 3`_ we describe our approach of varying the type systems at @@ -126,11 +110,11 @@ RPython programs to a variety of different platforms. Our current efforts, and the present paper, focus on this tool-suite. -We will not talk about the Standard Interpreter component of PyPy in the +We will not describe the Standard Interpreter component of PyPy in the sequel, other than mention that it is written in RPython and can thus be translated. At close to 90'000 lines of code, it is the largest RPython program that we have translated so far. More information can be found -in `[1]`_. +in `[S]`_. .. _`section 3`: @@ -140,7 +124,268 @@ ============================================================ -XXX +The translation process +----------------------- + +The translation process starts from RPython source code and eventually +produces low-level code suitable for the target environment. It can be +described as performing a series of step-wise transformations. Each +step is based on control flow graph transformations and rewriting, and +on the ability to augment the program with further implementation code +written in Python and analysed with the suitable type system. + +The front-end part of the translation process analyses the input RPython +program in two phases, as follows [#]_: + +.. [#] Note that the two phases are intermingled in time, because type + inference proceeds from an entry point function and follows all + calls, and thus only gradually discovers (the reachable parts of) + the input program. + +``[figure: flow graph and annotator, e.g. part of doc/image/translation.*]`` + +1. We take as input RPython functions, and convert them to control flow + graphs -- a structure amenable to analysis. These flow graphs contain + polymorphic operations only: in Python, almost all operations are + dynamically overloaded by type, whereas the absence of macros means + that the control flow is static. + +2. We perform type inference on the control flow graphs. At this stage, + types inferred are part of the type system which is the very definition + of the RPython sub-language: they are roughly a subset of Python's + built-in types, with some more precision to describe e.g. the + items stored in container types. Occasionally, a single input function + can produce several specialized versions, i.e. several similar but + differently typed graphs. This type inference process is described in + more details in `section 4`_. + +At the end of the front-end analysis, the input RPython program is +represented as a forest of flow graphs with typed variables. Following +this analysis are a number of transformation steps. Each transformation +step modifies the graphs in-place, by altering their structure and/or +the operations they contain. Each step inputs graphs typed in one type +system and leaves them typed in a possibly different type system, as we +will describe in the sequel. Finally, a back-end turns the resulting +graphs into code suitable for the target environment, e.g. C source code +ready to be compiled. + + +Transformations +--------------- + +When the translation target is C or C-like environments, the first of +the transformation steps takes the RPython-typed flow graphs, still +containing polymorphic operations only, and produces flow graphs with +monomorphic C-like operations and C-like types. In the simplest case, +this is the only transformation step: these graphs are directly fed to +the C back-end, which turns them into ANSI C source code. + +But RPython comes with automatic memory management, and this first +transformation step produces flow graphs that also assume automatic +memory management. Generating C code directly from there produces a +fully leaking program, unless we link it with an external garbage +collector (GC) like the Boehm conservative GC [Boehm], which is a viable +option. + +We have two alternatives, each implemented as a transformation step. +The first one inserts naive reference counting throughout the whole +program's graphs, which without further optimizations gives exceedingly +bad performance (it should be noted that the CPython interpreter is also +based on reference counting, and experience suggests that it was not a +bad choice in this particular case; more in `section 5`_). + +The other, and better, alternative is an exact GC, coupled with a +transformation, the *GC transformer*. It inputs C-level-typed graphs +and replaces all ``malloc`` operations with calls to a garbage +collector's innards. It can inspect all the graphs to discover the +``struct`` types in use by the program, and assign a unique type id to +each of them. These type ids are collected in internal tables that +describe the layout of the structures, e.g. their sizes and the location +of the pointer fields. + +We have implemented other transformations as well, e.g. performing +various optimizations, or turning the whole code into a +continuation-passing style (CPS) that allows us to use coroutines +without giving up the ability to generate fully ANSI C code. (This will +be the subject of another paper.) + +Finally, currently under development is a variant of the very first +transformation step, for use when targetting higher-level, +object-oriented (OO) environments. It is currently being designed +together with back-ends for Smalltalk/Squeak [#]_ and CLI/.NET. This +first transformation step, for C-like environments, is called the +*LLTyper*: it produces C-level flow graphs, where the object-oriented +features of RPython (classes and instances) become manipulations of C +structs with explicit virtual table pointers. By contrast, for OO +environments the transformation step is called the *OOTyper*: it targets +a simple object-oriented type system, and preserves the classes and +instances of the original RPython program. The LLTyper and OOTyper +still have much code in common, to convert the more Python-specific +features like its complex calling conventions. + +.. [#] Our simple OO type system is designed for *statically-typed* OO + environments, including Java; the presence of Smalltalk as a + back-end might be misleading in that respect. + +More information about these transformations can be found in `[T]`_. + + +System code +----------- + +A common pattern in all the transformation steps is to somehow lower the +level at which the graphs are currently expressed. Because of this, +there are operations that were atomic in the input (higher-level) graphs +but that need to be decomposed into several operations in the target +(lower-level) graphs. In some cases, the equivalent functionality +requires more than a couple of operations: a single operation must be +replaced by a call to whole new code -- functions and classes that serve +as helpers. An example of this is the ``malloc`` operation for the GC +transformer. Another example is the ``list.append()`` method, which is +atomic for Python or RPython programs, but needs to be replaced in +C-level code by a helper that possibly reallocates the array of items. + +This means that in addition to transforming the existing graphs, each +transformation step also needs to insert new functions into the forest. +A key feature of our approach is that we can write such "system-level" +code -- relevant only to a particular transformation -- in plain Python +as well: + +.. topic:: Figure 1 - a helper to implement ``list.append()`` + + :: + + def ll_append(lst, newitem): + # Append an item to the end of the vector. + index = lst.length # get the 'length' field + ll_resize(lst, index+1) # call a helper not shown here + itemsarray = lst.items # get the 'items' field + itemsarray[index] = item # this behaves like a C array + +The idea is to feed these new Python functions into the front-end, using +this time the transformation's target (lower-level) type system during +the type inference. In other words, we can write plain Python code that +manipulates objects that conform to the lower-level type system, and +have these functions automatically transformed into appropriately typed +graphs. + +For example, ``ll_append()`` in figure 1 is a Python function that +manipulates objects that behave like C structures and arrays. This +function is inserted by the LLTyper, as a helper to implement the +``list.append()`` calls found in its RPython-level input graphs. By +going through the front-end reconfigured to use C-level types, the above +function becomes a graph with such C-level types [#]_, which is then +indistinguishable from the other graphs of the forest produced by the +LLTyper. + +.. [#] The low-level type system specifies that the function should be + specialized by the C-level type of its input arguments, so it + actually turns into one graph per list type - list of integers, + list of pointers, etc. This behavior gives the programmer a + feeling comparable to C++ templates, without the declarations. + +In the example of the ``malloc`` operation, replaced by a call to GC +code, this GC code can invoke a complete collection of dead objects, and +can thus be arbitrarily complicated. Still, our GC code is entierely +written in plain Python, and it manipulates "objects" that are still at +a lower level: pointer and address objects. Even with the restriction +of having to use pointer-like and address-like objects, Python remains +more expressive than, say, C to write a GC. [see also Jikes] + +In the sequel, we will call *system code* functions written in Python +that are meant to be analysed by the front-end. For the purpose of this +article we will restrict this definition to helpers introduced by +transformations, as opposed to the original RPython program, although +the difference is not fundamental to the translation process (and +although our input RPython program, as seen in `section 2`_, is often +itself a Python virtual machine!). + +Note that such system code cannot typically be expressed as normal +RPython functions, because it corresponds to primitive operations at +that level. As an aside, let us remark that the number of primitive +operations at RPython level is, comparatively speaking, quite large: all +list and dictionary operations, instance and class attribute accesses, +many string processing methods, a good subset of all Python built-in +functions... Compared to other approaches [e.g. Squeak], we do not try +to minimize the number of primitives -- at least not at the source +level. It is fine to have many primitives at any high enough level, +because they can all be implemented at the next lower level in a way +that makes sense to that level. The key reason why this is not +burdensome is that the lower level implementations are also written in +Python - with the only difference that they use (and have to be typeable +in) the lower-level type system. [#]_ + +.. [#] This is not strictly true: the type systems are even allowed to + co-exist in the same function. The operations involving + higher-level type systems are turned into lower-level operations + by the previous transformations in the chain, which leave the + already-low-level operations untouched. + + +Type systems +------------ + +The four levels that we considered so far are summarized in figure 2. + +:: + + [figure 2: RPython + / \ + / \ + LLTypeSystem OOTypeSystem + / + / + Raw addresses + ] + +The RPython level is a subset of Python, so the types mostly follow +Python types, and the instances of these types are instances in the +normal Python sense; e.g. whereas Python has only got a single type +``list``, RPython has a parametric type ``list(T)`` for every RPython +type ``T``, but instances of ``list(T)`` are just those Python lists +whose items are all instances of ``T``. + +The other type systems, however, do not correspond to built-in Python +types. For each of them, we implemented: + +1. the types, which we use to tag the variables of the graphs at the + given level. (Types are mostly just annotated formal terms, and + would have been implemented simply as such if Python supported + them directly.) + +2. the Python objects that emulate instances of these types. (More + about them below.) + +We have defined well-typed operations between variables of these types, +plugging on the standard Python operators. These operations are the +ones that the emulating instances implement. As seen above, the types +can also be used by type inference when analysing system code like the +helpers of figure 1. + +Now, clearly, the purpose of types like a "C-like struct" or a "C-like +array" is to be translated to a real ``struct`` or array declaration by +the C back-end. What, then, is the purpose of emulating such things in +Python? The answer is three-fold. Firstly, if we have objects that +live within the Python interpreter, but faithfully emulate the behavior +of their C equivalent while performing additional safety checks, they +are an invaluable help for testing and debugging. For example, we can +check the correctness of our hash table implementation, written in +Python in term of struct- and array-like objects, just by running it. +The same holds for the GC. + +Secondly, and anecdotically, as the type inference process (`section +4`_) is based on abstract interpretation, we can use the following +trick: the resulting type of most low-level operations is deduced simply +by example. Sample C-level objects are instantiated, used as arguments +to a given operation, and produce a sample result, whose C-leve type +must be the type of the result variable in the graph. + +The third reason is fundamental: we use these emulating objects to +*represent* pre-built objects at that level. For example, the GC +transformer instantiates the objects emulating C arrays for the internal +type id tables, and it fills them with the correct values. These array +objects are then either used directly when testing the GC, or translated +by the C back-end into static pre-initialized arrays. @@ -151,6 +396,22 @@ ============================================================ +The various analyses used -- from type inference to lifetime analysis -- +are generally formulated as `abstract interpretation`_. While this +approach is known to be less efficient than more tailored algorithms +like constraint-based type inference, we gain in freedom, +controllability and simplicity. This proved essential in our overall +approach: as described in `section 3`_, we need to perform type +inference with many different type systems, the details of which are +still evolving. We mitigate the potential efficiency problem by wise +choices and compromises for the domain used; the foremost example of +this is that our RPython type inference performs almost no automatic +specialization of functions. We achieved enough precision for our +purpose, though, and in order to use the PyPy Standard Interpreter as +the source RPython program we had to add only a few explicit +specialization annotations manually. + + XXX @@ -198,4 +459,6 @@ XXX -.. _`[1]`: http://codespeak.net/pypy/dist/pypy/doc/architecture.html#the-standard-interpreter +.. _`[S]`: http://codespeak.net/pypy/dist/pypy/doc/architecture.html#the-standard-interpreter +.. _`[T]`: http://codespeak.net/pypy/dist/pypy/doc/translation.html +.. _`abstract interpretation`: http://en.wikipedia.org/wiki/Abstract_interpretation From pedronis at codespeak.net Fri May 26 21:49:34 2006 From: pedronis at codespeak.net (pedronis at codespeak.net) Date: Fri, 26 May 2006 21:49:34 +0200 (CEST) Subject: [pypy-svn] r27743 - pypy/extradoc/talk/dls2006 Message-ID: <20060526194934.7FE3110097@code0.codespeak.net> Author: pedronis Date: Fri May 26 21:49:33 2006 New Revision: 27743 Modified: pypy/extradoc/talk/dls2006/draft.txt Log: a note. and a comment. Modified: pypy/extradoc/talk/dls2006/draft.txt ============================================================================== --- pypy/extradoc/talk/dls2006/draft.txt (original) +++ pypy/extradoc/talk/dls2006/draft.txt Fri May 26 21:49:33 2006 @@ -144,12 +144,21 @@ ``[figure: flow graph and annotator, e.g. part of doc/image/translation.*]`` -1. We take as input RPython functions, and convert them to control flow +1. We take as input RPython functions [#]_, and convert them to control flow graphs -- a structure amenable to analysis. These flow graphs contain polymorphic operations only: in Python, almost all operations are dynamically overloaded by type, whereas the absence of macros means that the control flow is static. +.. [#] The input to our translation chain are indeed loaded + runtime function objects, not source code or ASTs, this + allows us to use unrestricted python for meta-programming + purposes at load time, in a seemingly staged programming approach, + in which the whole of the source program as Python program + produces the RPython program input to the tool-chain as the + object graph loaded in memory, and in particular the relevant + functions. + 2. We perform type inference on the control flow graphs. At this stage, types inferred are part of the type system which is the very definition of the RPython sub-language: they are roughly a subset of Python's @@ -205,7 +214,8 @@ We have implemented other transformations as well, e.g. performing various optimizations, or turning the whole code into a -continuation-passing style (CPS) that allows us to use coroutines +continuation-passing style (CPS) [I'm not sure our transformation +can be classified as classical CPS, although there are known similar techniques but the terminology is quite confused] that allows us to use coroutines without giving up the ability to generate fully ANSI C code. (This will be the subject of another paper.) From pedronis at codespeak.net Fri May 26 21:56:51 2006 From: pedronis at codespeak.net (pedronis at codespeak.net) Date: Fri, 26 May 2006 21:56:51 +0200 (CEST) Subject: [pypy-svn] r27744 - pypy/extradoc/talk/dls2006 Message-ID: <20060526195651.771D510097@code0.codespeak.net> Author: pedronis Date: Fri May 26 21:56:50 2006 New Revision: 27744 Modified: pypy/extradoc/talk/dls2006/draft.txt Log: fix some typos Modified: pypy/extradoc/talk/dls2006/draft.txt ============================================================================== --- pypy/extradoc/talk/dls2006/draft.txt (original) +++ pypy/extradoc/talk/dls2006/draft.txt Fri May 26 21:56:50 2006 @@ -220,7 +220,7 @@ be the subject of another paper.) Finally, currently under development is a variant of the very first -transformation step, for use when targetting higher-level, +transformation step, for use when targeting higher-level, object-oriented (OO) environments. It is currently being designed together with back-ends for Smalltalk/Squeak [#]_ and CLI/.NET. This first transformation step, for C-like environments, is called the @@ -296,7 +296,7 @@ In the example of the ``malloc`` operation, replaced by a call to GC code, this GC code can invoke a complete collection of dead objects, and -can thus be arbitrarily complicated. Still, our GC code is entierely +can thus be arbitrarily complicated. Still, our GC code is entirely written in plain Python, and it manipulates "objects" that are still at a lower level: pointer and address objects. Even with the restriction of having to use pointer-like and address-like objects, Python remains @@ -387,7 +387,7 @@ 4`_) is based on abstract interpretation, we can use the following trick: the resulting type of most low-level operations is deduced simply by example. Sample C-level objects are instantiated, used as arguments -to a given operation, and produce a sample result, whose C-leve type +to a given operation, and produce a sample result, whose C-level type must be the type of the result variable in the graph. The third reason is fundamental: we use these emulating objects to From pedronis at codespeak.net Fri May 26 22:01:10 2006 From: pedronis at codespeak.net (pedronis at codespeak.net) Date: Fri, 26 May 2006 22:01:10 +0200 (CEST) Subject: [pypy-svn] r27745 - pypy/extradoc/talk/dls2006 Message-ID: <20060526200110.E39C010098@code0.codespeak.net> Author: pedronis Date: Fri May 26 22:01:09 2006 New Revision: 27745 Modified: pypy/extradoc/talk/dls2006/draft.txt Log: comment to link with references Modified: pypy/extradoc/talk/dls2006/draft.txt ============================================================================== --- pypy/extradoc/talk/dls2006/draft.txt (original) +++ pypy/extradoc/talk/dls2006/draft.txt Fri May 26 22:01:09 2006 @@ -472,3 +472,6 @@ .. _`[S]`: http://codespeak.net/pypy/dist/pypy/doc/architecture.html#the-standard-interpreter .. _`[T]`: http://codespeak.net/pypy/dist/pypy/doc/translation.html .. _`abstract interpretation`: http://en.wikipedia.org/wiki/Abstract_interpretation + +.. http://www.cs.jhu.edu/~scott/pll/constraints.html page to the reference + /recent result for constraint-based type inference From njriley at codespeak.net Fri May 26 22:30:58 2006 From: njriley at codespeak.net (njriley at codespeak.net) Date: Fri, 26 May 2006 22:30:58 +0200 (CEST) Subject: [pypy-svn] r27747 - in pypy/branch/njriley-trans/pypy: module/trans rpython/module translator/c translator/c/src Message-ID: <20060526203058.448121009A@code0.codespeak.net> Author: njriley Date: Fri May 26 22:30:57 2006 New Revision: 27747 Modified: pypy/branch/njriley-trans/pypy/module/trans/__init__.py pypy/branch/njriley-trans/pypy/module/trans/interp_trans.py pypy/branch/njriley-trans/pypy/module/trans/rtrans.py pypy/branch/njriley-trans/pypy/rpython/module/ll_trans.py pypy/branch/njriley-trans/pypy/translator/c/extfunc.py pypy/branch/njriley-trans/pypy/translator/c/src/ll_trans.h Log: Exposed retry to applevel, auto syscall stuff to other C code; refactored code a bit. Modified: pypy/branch/njriley-trans/pypy/module/trans/__init__.py ============================================================================== --- pypy/branch/njriley-trans/pypy/module/trans/__init__.py (original) +++ pypy/branch/njriley-trans/pypy/module/trans/__init__.py Fri May 26 22:30:57 2006 @@ -9,6 +9,7 @@ interpleveldefs = { 'begin' : 'interp_trans.begin', 'end' : 'interp_trans.end', + 'retry' : 'interp_trans.retry', 'abort' : 'interp_trans.abort', 'pause' : 'interp_trans.pause', 'unpause' : 'interp_trans.unpause', Modified: pypy/branch/njriley-trans/pypy/module/trans/interp_trans.py ============================================================================== --- pypy/branch/njriley-trans/pypy/module/trans/interp_trans.py (original) +++ pypy/branch/njriley-trans/pypy/module/trans/interp_trans.py Fri May 26 22:30:57 2006 @@ -10,6 +10,10 @@ rtrans.end() return space.w_None +def retry(space): + rtrans.retry() + return space.w_None + def abort(space): rtrans.abort() return space.w_None Modified: pypy/branch/njriley-trans/pypy/module/trans/rtrans.py ============================================================================== --- pypy/branch/njriley-trans/pypy/module/trans/rtrans.py (original) +++ pypy/branch/njriley-trans/pypy/module/trans/rtrans.py Fri May 26 22:30:57 2006 @@ -8,6 +8,9 @@ def end(): os.write(2, '= rtrans.end\n') +def retry(): + os.write(2, '= rtrans.retry\n') + def abort(): os.write(2, '= rtrans.abort\n') Modified: pypy/branch/njriley-trans/pypy/rpython/module/ll_trans.py ============================================================================== --- pypy/branch/njriley-trans/pypy/rpython/module/ll_trans.py (original) +++ pypy/branch/njriley-trans/pypy/rpython/module/ll_trans.py Fri May 26 22:30:57 2006 @@ -6,6 +6,10 @@ pass ll_trans_end.suggested_primitive = True +def ll_trans_retry(): + pass +ll_trans_retry.suggested_primitive = True + def ll_trans_abort(): pass ll_trans_abort.suggested_primitive = True Modified: pypy/branch/njriley-trans/pypy/translator/c/extfunc.py ============================================================================== --- pypy/branch/njriley-trans/pypy/translator/c/extfunc.py (original) +++ pypy/branch/njriley-trans/pypy/translator/c/extfunc.py Fri May 26 22:30:57 2006 @@ -57,6 +57,7 @@ ll_thread.ll_thread_get_ident: 'LL_thread_get_ident', ll_trans.ll_trans_begin: 'LL_trans_begin', ll_trans.ll_trans_end: 'LL_trans_end', + ll_trans.ll_trans_retry: 'LL_trans_retry', ll_trans.ll_trans_abort: 'LL_trans_abort', ll_trans.ll_trans_pause: 'LL_trans_pause', ll_trans.ll_trans_unpause: 'LL_trans_unpause', Modified: pypy/branch/njriley-trans/pypy/translator/c/src/ll_trans.h ============================================================================== --- pypy/branch/njriley-trans/pypy/translator/c/src/ll_trans.h (original) +++ pypy/branch/njriley-trans/pypy/translator/c/src/ll_trans.h Fri May 26 22:30:57 2006 @@ -4,6 +4,7 @@ /* prototypes */ void LL_trans_begin(void); void LL_trans_end(void); +void LL_trans_retry(void); void LL_trans_abort(void); void LL_trans_pause(void); void LL_trans_unpause(void); @@ -12,6 +13,7 @@ void LL_trans_disable(void); int RPyTransPause(void); void RPyTransUnpause(int pause_state); +void RPyTransSurroundSyscalls(int surround); /* implementations */ @@ -32,6 +34,12 @@ } void +LL_trans_retry(void) +{ + XACT_RETRY; +} + +void LL_trans_abort(void) { XACT_ABORT(&&abort); @@ -55,6 +63,19 @@ XACT_UNPAUSE(pause_state); } +void +RPyTransSurroundSyscalls(int surround) +{ + if (surround) { + int pause_state; + XACT_PAUSE(pause_state); + set_auto_xact(1); + XACT_UNPAUSE(pause_state); + } else { + set_auto_xact(0); + } +} + static __thread int pause_state; void @@ -100,16 +121,14 @@ assert(ret_val == 0); } XACT_BEGIN; - XACT_PAUSE(ret_val); - set_auto_xact(1); - XACT_UNPAUSE(ret_val); + RPyTransSurroundSyscalls(1); XACT_END; } void LL_trans_disable(void) { - set_auto_xact(0); + RPyTransSurroundSyscalls(0); } int From antocuni at codespeak.net Sat May 27 10:18:00 2006 From: antocuni at codespeak.net (antocuni at codespeak.net) Date: Sat, 27 May 2006 10:18:00 +0200 (CEST) Subject: [pypy-svn] r27749 - pypy/dist/pypy/translator/cli/test Message-ID: <20060527081800.A7300100B3@code0.codespeak.net> Author: antocuni Date: Sat May 27 10:17:43 2006 New Revision: 27749 Modified: pypy/dist/pypy/translator/cli/test/runtest.py pypy/dist/pypy/translator/cli/test/test_runtest.py Log: Fixed a bug in CliTest.interpret_raises. Modified: pypy/dist/pypy/translator/cli/test/runtest.py ============================================================================== --- pypy/dist/pypy/translator/cli/test/runtest.py (original) +++ pypy/dist/pypy/translator/cli/test/runtest.py Sat May 27 10:17:43 2006 @@ -211,8 +211,8 @@ import exceptions # needed by eval res = self.interpret(fn, args) assert isinstance(res, ExceptionWrapper) - assert eval(res.class_name) is exception - + assert issubclass(eval(res.class_name), exception) + def ll_to_string(self, s): py.test.skip('ll_to_string not supported, yet') Modified: pypy/dist/pypy/translator/cli/test/test_runtest.py ============================================================================== --- pypy/dist/pypy/translator/cli/test/test_runtest.py (original) +++ pypy/dist/pypy/translator/cli/test/test_runtest.py Sat May 27 10:17:43 2006 @@ -35,3 +35,8 @@ def fn(): raise ValueError self.interpret_raises(ValueError, fn, []) + + def test_exception_subclass(self): + def fn(): + raise IndexError + self.interpret_raises(LookupError, fn, []) From antocuni at codespeak.net Sat May 27 12:03:38 2006 From: antocuni at codespeak.net (antocuni at codespeak.net) Date: Sat, 27 May 2006 12:03:38 +0200 (CEST) Subject: [pypy-svn] r27750 - in pypy/dist/pypy/translator/cli: . test Message-ID: <20060527100338.D78E6100B3@code0.codespeak.net> Author: antocuni Date: Sat May 27 12:03:27 2006 New Revision: 27750 Modified: pypy/dist/pypy/translator/cli/gencli.py pypy/dist/pypy/translator/cli/opcodes.py pypy/dist/pypy/translator/cli/test/runtest.py pypy/dist/pypy/translator/cli/test/test_op.py Log: Fixed a bug that prevented code to compile when exception were not used. Added some char support. Modified: pypy/dist/pypy/translator/cli/gencli.py ============================================================================== --- pypy/dist/pypy/translator/cli/gencli.py (original) +++ pypy/dist/pypy/translator/cli/gencli.py Sat May 27 12:03:27 2006 @@ -9,7 +9,6 @@ from pypy.translator.cli.database import LowLevelDatabase from pypy.translator.cli.cts import CTS from pypy.translator.cli.opcodes import opcodes -from pypy.translator.squeak.node import LoopFinder class Tee(object): def __init__(self, *args): @@ -25,14 +24,18 @@ outfile.close() class GenCli(object): - def __init__(self, tmpdir, translator, entrypoint = None, type_system_class = CTS, \ - opcode_dict = opcodes, name_suffix = '.il', function_class = Function ): + def __init__(self, tmpdir, translator, entrypoint=None, type_system_class=CTS, + opcode_dict=opcodes, name_suffix='.il', function_class=Function, + pending_graphs=()): self.tmpdir = tmpdir self.translator = translator self.entrypoint = entrypoint self.db = LowLevelDatabase( type_system_class = type_system_class , opcode_dict = opcode_dict, function_class = function_class ) + for graph in pending_graphs: + self.db.pending_function(graph) + if entrypoint is None: self.assembly_name = self.translator.graphs[0].name else: Modified: pypy/dist/pypy/translator/cli/opcodes.py ============================================================================== --- pypy/dist/pypy/translator/cli/opcodes.py (original) +++ pypy/dist/pypy/translator/cli/opcodes.py Sat May 27 12:03:27 2006 @@ -55,12 +55,12 @@ 'bool_not': [PushAllArgs]+Not, - 'char_lt': None, - 'char_le': None, - 'char_eq': None, - 'char_ne': None, - 'char_gt': None, - 'char_ge': None, + 'char_lt': 'clt', + 'char_le': _not('cgt'), + 'char_eq': 'ceq', + 'char_ne': _not('ceq'), + 'char_gt': 'cgt', + 'char_ge': _not('clt'), 'unichar_eq': None, # should we unify unichar and char, as Jython does? 'unichar_ne': None, Modified: pypy/dist/pypy/translator/cli/test/runtest.py ============================================================================== --- pypy/dist/pypy/translator/cli/test/runtest.py (original) +++ pypy/dist/pypy/translator/cli/test/runtest.py Sat May 27 12:03:27 2006 @@ -126,10 +126,17 @@ ann.build_graph_types(graph, inputcells) t.graphs.insert(0, graph) else: - t.buildannotator().build_types(func, annotation) - + ann = t.buildannotator() + ann.build_types(func, annotation) + + # quick hack: force exceptions.Exception to be rendered + def raiseKeyError(): + raise KeyError + ann.build_types(raiseKeyError, []) + t.buildrtyper(type_system="ootype").specialize() self.graph = t.graphs[0] + raiseKeyError_graph = t.graphs[1] if getoption('view'): t.view() @@ -139,7 +146,7 @@ else: self.tmpdir = udir - return GenCli(self.tmpdir, t, TestEntryPoint(self.graph)) + return GenCli(self.tmpdir, t, TestEntryPoint(self.graph), pending_graphs=[raiseKeyError_graph]) def _build_exe(self): tmpfile = self._gen.generate_source() Modified: pypy/dist/pypy/translator/cli/test/test_op.py ============================================================================== --- pypy/dist/pypy/translator/cli/test/test_op.py (original) +++ pypy/dist/pypy/translator/cli/test/test_op.py Sat May 27 12:03:27 2006 @@ -1,35 +1,49 @@ from pypy.translator.cli.test.runtest import check from pypy.rpython.rarithmetic import r_uint, r_ulonglong, r_longlong - +from pypy.annotation import model as annmodel import sys +char = annmodel.SomeChar() + def test_op(): - yield check, op_any_ge, [int, int], (42, 42) - yield check, op_any_ge, [int, int], (13, 42) - yield check, op_any_le, [int, int], (42, 42) - yield check, op_any_le, [int, int], (13, 42) - +## yield check, op_any_ge, [int, int], (42, 42) +## yield check, op_any_ge, [int, int], (13, 42) +## yield check, op_any_le, [int, int], (42, 42) +## yield check, op_any_le, [int, int], (13, 42) + + yield check, op_any_eq, [char, char], ('a', 'a') + yield check, op_any_ne, [char, char], ('a', 'b') + yield check, op_any_ge, [char, char], ('a', 'b') + yield check, op_any_ge, [char, char], ('b', 'a') + yield check, op_any_le, [char, char], ('a', 'b') + yield check, op_any_le, [char, char], ('b', 'a') + for name, func in globals().iteritems(): if not name.startswith('op_'): continue any = '_any_' in name - if any or '_int_' in name: - yield check, func, [int, int], (42, 13) +## if any or '_int_' in name: +## yield check, func, [int, int], (42, 13) + +## if any or '_uint_' in name: +## yield check, func, [r_uint, r_uint], (r_uint(sys.maxint+1), r_uint(42)) - if any or '_uint_' in name: - yield check, func, [r_uint, r_uint], (r_uint(sys.maxint+1), r_uint(42)) +## if any or '_long_' in name: +## yield check, func, [r_longlong, r_longlong], (r_longlong(sys.maxint*3), r_longlong(42)) - if any or '_long_' in name: - yield check, func, [r_longlong, r_longlong], (r_longlong(sys.maxint*3), r_longlong(42)) +## if any or '_ulong_' in name: +## yield check, func, [r_ulonglong, r_ulonglong], (r_ulonglong(sys.maxint*3), r_ulonglong(42)) - if any or '_ulong_' in name: - yield check, func, [r_ulonglong, r_ulonglong], (r_ulonglong(sys.maxint*3), r_ulonglong(42)) +## if any or '_float_' in name: +## yield check, func, [float, float], (42.0, (10.0/3)) - if any or '_float_' in name: - yield check, func, [float, float], (42.0, (10.0/3)) +def op_any_eq(x, y): + return x == y +def op_any_ne(x, y): + return x != y def op_int_long_float_neg(x, y): return -x From arigo at codespeak.net Sat May 27 12:34:38 2006 From: arigo at codespeak.net (arigo at codespeak.net) Date: Sat, 27 May 2006 12:34:38 +0200 (CEST) Subject: [pypy-svn] r27757 - pypy/dist/pypy/translator/goal Message-ID: <20060527103438.72E2F10050@code0.codespeak.net> Author: arigo Date: Sat May 27 12:34:37 2006 New Revision: 27757 Added: pypy/dist/pypy/translator/goal/targetvarsized.py (contents, props changed) Modified: pypy/dist/pypy/translator/goal/translate.py Log: Added a target of variable size: it is built by exec'ing richards.py as many times as specified on the command line. Try: python translate.py targetvarsized.py 5 Added: pypy/dist/pypy/translator/goal/targetvarsized.py ============================================================================== --- (empty file) +++ pypy/dist/pypy/translator/goal/targetvarsized.py Sat May 27 12:34:37 2006 @@ -0,0 +1,60 @@ +import os, sys +#from pypy.translator.goal import richards + +modfilename = os.path.join(os.path.dirname(__file__), 'richards.py') + + +# Number of times richards is imported in parallel. +# Can be changed on the command line, e.g. +# +# translate.py targetvarsized.py 20 +# +DEFAULT_CODE_SIZE_FACTOR = 10 + + +# __________ Entry point __________ + +def richards_main(fn, iterations): + s = "Richards benchmark (RPython) starting...\n" + os.write(1, s) + result, startTime, endTime = fn(iterations) + if not result: + os.write(2, "Incorrect results!\n") + return False + os.write(1, "finished.\n") + total_s = endTime - startTime + avg = total_s * 1000 / iterations + os.write(1, "Total time for %d iterations: %f secs\n" %(iterations, total_s)) + os.write(1, "Average time per iteration: %f ms\n" %(avg)) + return True + + +def entry_point(argv): + for fn in functions: + if not richards_main(fn, 10): + return 1 + return 0 + +# _____ Define and setup target ___ + +def target(driver, args): + global modules, functions + if len(args) == 0: + N = DEFAULT_CODE_SIZE_FACTOR + elif len(args) == 1: + N = int(args[0]) + else: + raise ValueError("too many command-line arguments") + + modules = [] + functions = [] + f = open(modfilename) + source = f.read() + f.close() + for i in range(N): + d = {'__name__': 'richards%d' % i} + exec source in d + modules.append(d) + functions.append(d['entry_point']) + + return entry_point, None Modified: pypy/dist/pypy/translator/goal/translate.py ============================================================================== --- pypy/dist/pypy/translator/goal/translate.py (original) +++ pypy/dist/pypy/translator/goal/translate.py Sat May 27 12:34:37 2006 @@ -159,6 +159,7 @@ thismod = sys.modules[__name__] targetspec_dic = { '__name__': os.path.splitext(os.path.basename(targetspec))[0], + '__file__': targetspec, 'translate': thismod} sys.path.insert(0, os.path.dirname(targetspec)) execfile(targetspec, targetspec_dic) From arigo at codespeak.net Sat May 27 13:04:34 2006 From: arigo at codespeak.net (arigo at codespeak.net) Date: Sat, 27 May 2006 13:04:34 +0200 (CEST) Subject: [pypy-svn] r27758 - pypy/extradoc/talk/dls2006 Message-ID: <20060527110434.8781D100BA@code0.codespeak.net> Author: arigo Date: Sat May 27 13:04:33 2006 New Revision: 27758 Modified: pypy/extradoc/talk/dls2006/draft.txt Log: Mention that types are self-recursive. Modified: pypy/extradoc/talk/dls2006/draft.txt ============================================================================== --- pypy/extradoc/talk/dls2006/draft.txt (original) +++ pypy/extradoc/talk/dls2006/draft.txt Sat May 27 13:04:33 2006 @@ -359,9 +359,9 @@ types. For each of them, we implemented: 1. the types, which we use to tag the variables of the graphs at the - given level. (Types are mostly just annotated formal terms, and - would have been implemented simply as such if Python supported - them directly.) + given level. (Types are actually annotated, self-recursive formal + terms, and would have been implemented simply as such if Python + supported them directly.) 2. the Python objects that emulate instances of these types. (More about them below.) From antocuni at codespeak.net Sat May 27 13:37:54 2006 From: antocuni at codespeak.net (antocuni at codespeak.net) Date: Sat, 27 May 2006 13:37:54 +0200 (CEST) Subject: [pypy-svn] r27760 - in pypy/dist/pypy/translator/cli: src test Message-ID: <20060527113754.1D7A5100BB@code0.codespeak.net> Author: antocuni Date: Sat May 27 13:37:44 2006 New Revision: 27760 Modified: pypy/dist/pypy/translator/cli/src/pypylib.cs pypy/dist/pypy/translator/cli/test/runtest.py Log: Some little bugs fixed. Modified: pypy/dist/pypy/translator/cli/src/pypylib.cs ============================================================================== --- pypy/dist/pypy/translator/cli/src/pypylib.cs (original) +++ pypy/dist/pypy/translator/cli/src/pypylib.cs Sat May 27 13:37:44 2006 @@ -9,6 +9,8 @@ public static string ToPython(bool x) { return x.ToString(); } public static string ToPython(double x) { return x.ToString(); } public static string ToPython(char x) { return string.Format("'{0}'", x); } + public static string ToPython(uint x) { return x.ToString(); } + public static string ToPython(long x) { return x.ToString(); } public static string ToPython(object obj) { Modified: pypy/dist/pypy/translator/cli/test/runtest.py ============================================================================== --- pypy/dist/pypy/translator/cli/test/runtest.py (original) +++ pypy/dist/pypy/translator/cli/test/runtest.py Sat May 27 13:37:44 2006 @@ -136,7 +136,11 @@ t.buildrtyper(type_system="ootype").specialize() self.graph = t.graphs[0] - raiseKeyError_graph = t.graphs[1] + + # XXX: horrible hack :-( + for graph in t.graphs: + if graph.name == 'raiseKeyError': + raiseKeyError_graph = graph if getoption('view'): t.view() From ericvrp at codespeak.net Sat May 27 14:11:43 2006 From: ericvrp at codespeak.net (ericvrp at codespeak.net) Date: Sat, 27 May 2006 14:11:43 +0200 (CEST) Subject: [pypy-svn] r27761 - pypy/dist/pypy/translator/oosupport Message-ID: <20060527121143.3B13F100B7@code0.codespeak.net> Author: ericvrp Date: Sat May 27 14:11:42 2006 New Revision: 27761 Added: pypy/dist/pypy/translator/oosupport/ pypy/dist/pypy/translator/oosupport/README.txt (contents, props changed) Log: This directory will contain code and tests that can be shared between the various ootypesystem based backends. Added: pypy/dist/pypy/translator/oosupport/README.txt ============================================================================== --- (empty file) +++ pypy/dist/pypy/translator/oosupport/README.txt Sat May 27 14:11:42 2006 @@ -0,0 +1,2 @@ +This directory will contain code and tests that can be shared between +the various ootypesystem based backends. From ale at codespeak.net Sat May 27 14:15:05 2006 From: ale at codespeak.net (ale at codespeak.net) Date: Sat, 27 May 2006 14:15:05 +0200 (CEST) Subject: [pypy-svn] r27762 - pypy/dist/pypy/lib/pyontology Message-ID: <20060527121505.8BB62100B7@code0.codespeak.net> Author: ale Date: Sat May 27 14:15:04 2006 New Revision: 27762 Modified: pypy/dist/pypy/lib/pyontology/constraint_classes.py pypy/dist/pypy/lib/pyontology/pyontology.py Log: Bugfixes Modified: pypy/dist/pypy/lib/pyontology/constraint_classes.py ============================================================================== --- pypy/dist/pypy/lib/pyontology/constraint_classes.py (original) +++ pypy/dist/pypy/lib/pyontology/constraint_classes.py Sat May 27 14:15:04 2006 @@ -28,10 +28,10 @@ cost = 10 - def __init__(self, prop, var, comp): + def __init__(self, prop, restr, var, comp): AbstractConstraint.__init__(self, [prop]) self.check_individual = "domains['%s'].getValues() != []" % prop - self.formula = "len(domains['%s'].getValuesPrKey('%s')) %s int(%s)"% (prop, var, comp, var) + self.formula = "len(domains['%s'].getValuesPrKey('%s')) %s int(%s)"% (prop, restr, comp, var) def estimateCost(self, domains): return self.cost Modified: pypy/dist/pypy/lib/pyontology/pyontology.py ============================================================================== --- pypy/dist/pypy/lib/pyontology/pyontology.py (original) +++ pypy/dist/pypy/lib/pyontology/pyontology.py Sat May 27 14:15:04 2006 @@ -111,7 +111,7 @@ def __init__(self, name='', values=[], bases = []): ClassDomain.__init__(self, name, values, bases) - self.constraint = ListConstraint(name) +# self.constraint = ListConstraint(name) class Property(Thing): # Property contains the relationship between a class instance and a value @@ -181,7 +181,7 @@ def __init__(self, name='', values=[], bases = []): ClassDomain.__init__(self, name, values, bases) self.constraint = NothingConstraint(name) - + class FunctionalProperty(Property): def __init__(self, name='', values=[], bases = []): @@ -363,7 +363,10 @@ if not cls: return var if not var in self.variables: - self.variables[var] = cls(var) + cls = self.variables[var] = cls(var) + if hasattr(cls, 'constraint'): + log("make_var constraint 1 %r,%r" %(cls,a)) + self.constraints.append(cls.constraint) # XXX needed because of old style classes elif issubclass(cls, self.variables[var].__class__): vals = self.variables[var].getValues() @@ -371,6 +374,9 @@ tmp.setValues(vals) tmp.property = self.variables[var].property tmp.TBox = self.variables[var].TBox + if hasattr(tmp, 'constraint'): + log("make_var constraint 2 %r,%r" %(cls,a)) + self.constraints.append(tmp.constraint) self.variables[var] = tmp return var @@ -417,7 +423,7 @@ avar = self.make_var(List, rdf_list) lis = list(self.graph.objects(rdf_list, rdf_first)) if not lis: - return res + return avar res.append(lis[0]) lis = list(self.graph.objects(rdf_list, rdf_rest))[0] while lis != rdf_nil: @@ -636,9 +642,14 @@ svar =self.make_var(Restriction, s) prop = self.variables[svar].property assert prop + cls = list(self.graph.triples((None, None, s))) + if cls: + cls = cls[0][0] + else: + cls = var comp = {'max': '<', 'min': '>'}.get(card, '=') self.variables[svar].TBox[prop] = {'Cardinality': [( comp, int(var))]} - self.constraints.append(CardinalityConstraint(prop, var, comp+'=')) + self.constraints.append(CardinalityConstraint(prop, cls, var, comp+'=')) def maxCardinality(self, s, var): """ Len of finite domain of the property shall be less than or equal to var""" From antocuni at codespeak.net Sat May 27 14:40:38 2006 From: antocuni at codespeak.net (antocuni at codespeak.net) Date: Sat, 27 May 2006 14:40:38 +0200 (CEST) Subject: [pypy-svn] r27763 - in pypy/dist/pypy/translator/cli: . src test Message-ID: <20060527124038.7822D100B7@code0.codespeak.net> Author: antocuni Date: Sat May 27 14:40:25 2006 New Revision: 27763 Modified: pypy/dist/pypy/translator/cli/cts.py pypy/dist/pypy/translator/cli/database.py pypy/dist/pypy/translator/cli/opcodes.py pypy/dist/pypy/translator/cli/src/pypylib.cs pypy/dist/pypy/translator/cli/test/runtest.py pypy/dist/pypy/translator/cli/test/test_op.py Log: Added support for unicode character. Some bugfixes. Modified: pypy/dist/pypy/translator/cli/cts.py ============================================================================== --- pypy/dist/pypy/translator/cli/cts.py (original) +++ pypy/dist/pypy/translator/cli/cts.py Sat May 27 14:40:25 2006 @@ -4,9 +4,7 @@ import exceptions -#from pypy.rpython.lltypesystem.lltype import Signed, Unsigned, Void, Bool, Float from pypy.rpython.lltypesystem.lltype import SignedLongLong, UnsignedLongLong -#from pypy.rpython.ootypesystem.ootype import Instance, Class, StaticMethod, List, Record, Dict from pypy.rpython.ootypesystem import ootype from pypy.translator.cli.option import getoption from pypy.translator.cli import oopspec @@ -29,6 +27,7 @@ ootype.Bool: 'bool', ootype.Float: 'float64', ootype.Char: 'char', + ootype.UniChar: 'char', ootype.Class: 'class [mscorlib]System.Type', # maps generic types to their ordinal Modified: pypy/dist/pypy/translator/cli/database.py ============================================================================== --- pypy/dist/pypy/translator/cli/database.py (original) +++ pypy/dist/pypy/translator/cli/database.py Sat May 27 14:40:25 2006 @@ -141,7 +141,7 @@ pass elif TYPE is ootype.Bool: ilasm.opcode('ldc.i4', str(int(value))) - elif TYPE is ootype.Char: + elif TYPE is ootype.Char or TYPE is ootype.UniChar: ilasm.opcode('ldc.i4', ord(value)) elif TYPE is ootype.Float: ilasm.opcode('ldc.r8', repr(value)) Modified: pypy/dist/pypy/translator/cli/opcodes.py ============================================================================== --- pypy/dist/pypy/translator/cli/opcodes.py (original) +++ pypy/dist/pypy/translator/cli/opcodes.py Sat May 27 14:40:25 2006 @@ -62,8 +62,8 @@ 'char_gt': 'cgt', 'char_ge': _not('clt'), - 'unichar_eq': None, # should we unify unichar and char, as Jython does? - 'unichar_ne': None, + 'unichar_eq': 'ceq', + 'unichar_ne': _not('ceq'), 'int_is_true': DoNothing, 'int_neg': 'neg', @@ -187,7 +187,7 @@ 'ullong_lt': 'clt.un', 'ullong_le': _not('cgt.un'), 'ullong_eq': 'ceq', - 'ullong_ne': _not('ceq.un'), + 'ullong_ne': _not('ceq'), 'ullong_gt': 'cgt.un', 'ullong_ge': _not('clt.un'), Modified: pypy/dist/pypy/translator/cli/src/pypylib.cs ============================================================================== --- pypy/dist/pypy/translator/cli/src/pypylib.cs (original) +++ pypy/dist/pypy/translator/cli/src/pypylib.cs Sat May 27 14:40:25 2006 @@ -11,6 +11,7 @@ public static string ToPython(char x) { return string.Format("'{0}'", x); } public static string ToPython(uint x) { return x.ToString(); } public static string ToPython(long x) { return x.ToString(); } + public static string ToPython(ulong x) { return x.ToString(); } public static string ToPython(object obj) { Modified: pypy/dist/pypy/translator/cli/test/runtest.py ============================================================================== --- pypy/dist/pypy/translator/cli/test/runtest.py (original) +++ pypy/dist/pypy/translator/cli/test/runtest.py Sat May 27 14:40:25 2006 @@ -173,14 +173,13 @@ arglist = SDK.runtime() + [self._exe] + map(str, args) env = os.environ.copy() - env['LANG'] = 'C' + env['LANG'] = 'C' mono = subprocess.Popen(arglist, stdout=subprocess.PIPE, stderr=subprocess.PIPE, env=env) stdout, stderr = mono.communicate() retval = mono.wait() assert retval == 0, stderr - print stdout res = eval(stdout) if isinstance(res, tuple): res = StructTuple(res) # so tests can access tuple elements with .item0, .item1, etc. Modified: pypy/dist/pypy/translator/cli/test/test_op.py ============================================================================== --- pypy/dist/pypy/translator/cli/test/test_op.py (original) +++ pypy/dist/pypy/translator/cli/test/test_op.py Sat May 27 14:40:25 2006 @@ -6,10 +6,10 @@ char = annmodel.SomeChar() def test_op(): -## yield check, op_any_ge, [int, int], (42, 42) -## yield check, op_any_ge, [int, int], (13, 42) -## yield check, op_any_le, [int, int], (42, 42) -## yield check, op_any_le, [int, int], (13, 42) + yield check, op_any_ge, [int, int], (42, 42) + yield check, op_any_ge, [int, int], (13, 42) + yield check, op_any_le, [int, int], (42, 42) + yield check, op_any_le, [int, int], (13, 42) yield check, op_any_eq, [char, char], ('a', 'a') yield check, op_any_ne, [char, char], ('a', 'b') @@ -18,25 +18,36 @@ yield check, op_any_le, [char, char], ('a', 'b') yield check, op_any_le, [char, char], ('b', 'a') + yield check, op_unichar_eq, [int, int], (0, 0) + yield check, op_unichar_ne, [int, int], (0, 1) + for name, func in globals().iteritems(): if not name.startswith('op_'): continue any = '_any_' in name -## if any or '_int_' in name: -## yield check, func, [int, int], (42, 13) + if any or '_int_' in name: + yield check, func, [int, int], (42, 13) + + if any or '_uint_' in name: + yield check, func, [r_uint, r_uint], (r_uint(sys.maxint+1), r_uint(42)) + + if any or '_long_' in name: + yield check, func, [r_longlong, r_longlong], (r_longlong(sys.maxint*3), r_longlong(42)) -## if any or '_uint_' in name: -## yield check, func, [r_uint, r_uint], (r_uint(sys.maxint+1), r_uint(42)) + if any or '_ulong_' in name: + yield check, func, [r_ulonglong, r_ulonglong], (r_ulonglong(sys.maxint*3), r_ulonglong(42)) -## if any or '_long_' in name: -## yield check, func, [r_longlong, r_longlong], (r_longlong(sys.maxint*3), r_longlong(42)) + if any or '_float_' in name: + yield check, func, [float, float], (42.0, (10.0/3)) -## if any or '_ulong_' in name: -## yield check, func, [r_ulonglong, r_ulonglong], (r_ulonglong(sys.maxint*3), r_ulonglong(42)) +def op_unichar_eq(x, y): + const = [u'\u03b1', u'\u03b2'] + return const[x] == const[y] -## if any or '_float_' in name: -## yield check, func, [float, float], (42.0, (10.0/3)) +def op_unichar_ne(x, y): + const = [u'\u03b1', u'\u03b2'] + return const[x] != const[y] def op_any_eq(x, y): From sanxiyn at codespeak.net Sat May 27 17:07:57 2006 From: sanxiyn at codespeak.net (sanxiyn at codespeak.net) Date: Sat, 27 May 2006 17:07:57 +0200 (CEST) Subject: [pypy-svn] r27764 - pypy/dist/pypy/translator/cl Message-ID: <20060527150757.D769C10071@code0.codespeak.net> Author: sanxiyn Date: Sat May 27 17:07:54 2006 New Revision: 27764 Modified: pypy/dist/pypy/translator/cl/gencl.py Log: Unused variable Modified: pypy/dist/pypy/translator/cl/gencl.py ============================================================================== --- pypy/dist/pypy/translator/cl/gencl.py (original) +++ pypy/dist/pypy/translator/cl/gencl.py Sat May 27 17:07:54 2006 @@ -243,7 +243,6 @@ yield "))" def emit_block(self, block): - self.cur_block = block tag = self.blockref[block] yield "tag" + clrepr(str(tag), True) if block.exitswitch is c_last_exception: From sanxiyn at codespeak.net Sat May 27 17:14:44 2006 From: sanxiyn at codespeak.net (sanxiyn at codespeak.net) Date: Sat, 27 May 2006 17:14:44 +0200 (CEST) Subject: [pypy-svn] r27765 - pypy/dist/pypy/translator/cl Message-ID: <20060527151444.D6EE110071@code0.codespeak.net> Author: sanxiyn Date: Sat May 27 17:14:41 2006 New Revision: 27765 Modified: pypy/dist/pypy/translator/cl/gencl.py Log: Small simplification Modified: pypy/dist/pypy/translator/cl/gencl.py ============================================================================== --- pypy/dist/pypy/translator/cl/gencl.py (original) +++ pypy/dist/pypy/translator/cl/gencl.py Sat May 27 17:14:41 2006 @@ -245,7 +245,8 @@ def emit_block(self, block): tag = self.blockref[block] yield "tag" + clrepr(str(tag), True) - if block.exitswitch is c_last_exception: + handle_exc = block.exitswith == c_last_exception + if handle_exc: yield "(handler-case (progn" for op in block.operations: emit_op = OpFormatter(self, op) @@ -308,7 +309,7 @@ else: retval = clrepr(block.inputargs[0]) yield "(return %s)" % clrepr(retval, True) - if block.exitswitch is c_last_exception: + if handle_exc: yield ")" def format_jump(self, block): From sanxiyn at codespeak.net Sat May 27 17:17:59 2006 From: sanxiyn at codespeak.net (sanxiyn at codespeak.net) Date: Sat, 27 May 2006 17:17:59 +0200 (CEST) Subject: [pypy-svn] r27766 - pypy/dist/pypy/translator/cl Message-ID: <20060527151759.C62571005A@code0.codespeak.net> Author: sanxiyn Date: Sat May 27 17:17:56 2006 New Revision: 27766 Modified: pypy/dist/pypy/translator/cl/gencl.py Log: oops Modified: pypy/dist/pypy/translator/cl/gencl.py ============================================================================== --- pypy/dist/pypy/translator/cl/gencl.py (original) +++ pypy/dist/pypy/translator/cl/gencl.py Sat May 27 17:17:56 2006 @@ -245,7 +245,7 @@ def emit_block(self, block): tag = self.blockref[block] yield "tag" + clrepr(str(tag), True) - handle_exc = block.exitswith == c_last_exception + handle_exc = block.exitswitch == c_last_exception if handle_exc: yield "(handler-case (progn" for op in block.operations: From sanxiyn at codespeak.net Sat May 27 17:28:28 2006 From: sanxiyn at codespeak.net (sanxiyn at codespeak.net) Date: Sat, 27 May 2006 17:28:28 +0200 (CEST) Subject: [pypy-svn] r27767 - pypy/dist/pypy/translator/cl Message-ID: <20060527152828.B682D100A0@code0.codespeak.net> Author: sanxiyn Date: Sat May 27 17:28:24 2006 New Revision: 27767 Modified: pypy/dist/pypy/translator/cl/gencl.py Log: Reorder code Modified: pypy/dist/pypy/translator/cl/gencl.py ============================================================================== --- pypy/dist/pypy/translator/cl/gencl.py (original) +++ pypy/dist/pypy/translator/cl/gencl.py Sat May 27 17:28:24 2006 @@ -253,7 +253,14 @@ for line in emit_op: yield line exits = block.exits - if len(exits) == 1: + if len(exits) == 0: + if len(block.inputargs) == 2: + exc_value = clrepr(block.inputargs[1]) + yield "(error %s)" % (exc_value,) + else: + retval = clrepr(block.inputargs[0]) + yield "(return %s)" % (retval,) + elif len(exits) == 1: for line in self.emit_link(exits[0]): yield line elif len(exits) > 1: @@ -303,12 +310,6 @@ for line in self.emit_link(exits[-1]): yield line yield ")" * len(exits) - elif len(block.inputargs) == 2: - exc_value = clrepr(block.inputargs[1], True) - yield "(error %s)" % (exc_value,) - else: - retval = clrepr(block.inputargs[0]) - yield "(return %s)" % clrepr(retval, True) if handle_exc: yield ")" From tismer at codespeak.net Sat May 27 17:32:22 2006 From: tismer at codespeak.net (tismer at codespeak.net) Date: Sat, 27 May 2006 17:32:22 +0200 (CEST) Subject: [pypy-svn] r27768 - in pypy/dist/pypy/translator: c tool Message-ID: <20060527153222.18C3F100A0@code0.codespeak.net> Author: tismer Date: Sat May 27 17:32:20 2006 New Revision: 27768 Modified: pypy/dist/pypy/translator/c/pyobj.py pypy/dist/pypy/translator/tool/raymond.py Log: getting more control over which methods get exposed and which not Modified: pypy/dist/pypy/translator/c/pyobj.py ============================================================================== --- pypy/dist/pypy/translator/c/pyobj.py (original) +++ pypy/dist/pypy/translator/c/pyobj.py Sat May 27 17:32:20 2006 @@ -7,6 +7,7 @@ from pypy.translator.gensupp import builtin_base, builtin_type_base from pypy.translator.c.support import log from pypy.translator.c.wrapper import gen_wrapper, new_method_graph +from pypy.translator.tool.raymond import should_expose_method from pypy.rpython.rarithmetic import r_int, r_uint from pypy.rpython.lltypesystem.lltype import pyobjectptr, LowLevelType @@ -568,6 +569,9 @@ if isinstance(value, FunctionType): func = value fname = '%s.%s' % (cls.__name__, func.__name__) + if not should_expose_method(func): + log.REMARK('method %s hidden from wrapper' % fname) + continue if func.__name__ == '__init__': init_seen = True # there is the problem with exposed classes inheriting from Modified: pypy/dist/pypy/translator/tool/raymond.py ============================================================================== --- pypy/dist/pypy/translator/tool/raymond.py (original) +++ pypy/dist/pypy/translator/tool/raymond.py Sat May 27 17:32:20 2006 @@ -42,7 +42,7 @@ if len(argstypelist) == 1: argstypelist = guess_methannotation(func, argstypelist[0]) missing = [object] * (func.func_code.co_argcount - len(argstypelist)) - return missing + argstypelist + return argstypelist + missing def guess_methannotation(func, cls): ret = [cls] @@ -57,7 +57,7 @@ return name in SPECIAL_METHODS or not name.startswith('_') def get_compiled_module(func, view=conftest.option.view, inline_threshold=1, - use_boehm=False, exports=None): + use_boehm=False, exports=None, expose_all=True): from pypy.translator.translator import TranslationContext from pypy.translator.backendopt.all import backend_optimizations @@ -85,7 +85,7 @@ rtyper.add_wrapper(clsdef) for obj in cls.__dict__.values(): if isinstance(obj, types.FunctionType): - if should_expose_method(obj): + if should_expose_method(obj) and expose_all: if not ann.bookkeeper.getdesc(obj).querycallfamily(): # not annotated, so enforce it ann.build_types(obj, get_annotation(obj, [cls]), complete_now=False) @@ -99,6 +99,8 @@ ann.build_types(obj, get_annotation(obj), complete_now=False) if obj.__name__ == '__init__': pyobj_options['use_true_methods'] = True + elif isinstance(obj, types.ClassType): + raise TypeError, 'old-style classes are not supported:%r' % obj all = [] for obj in exports: @@ -208,6 +210,9 @@ exec src def __init__(self): self._initialized = False + def _freeze_(self): + self._initialized = False + return False del __builtin__, name, obj, src bltn_singleton = BuiltinHelper() @@ -312,8 +317,9 @@ dic[name] = property(*stuff) class ExtCompiler(object): - def __init__(self, startupfunc, use_true_methods=True): + def __init__(self, startupfunc, use_true_methods=True, expose_all=True): self.startupfunc = startupfunc + self.expose_all = expose_all self.exports = {} if use_true_methods: self.export(__init__) @@ -325,5 +331,6 @@ self.exports[obj.__name__] = obj def build(self, modname): - mod = get_compiled_module(self.startupfunc, exports=self.exports.values()) + mod = get_compiled_module(self.startupfunc, exports=self.exports.values(), + expose_all=self.expose_all) return mod From sanxiyn at codespeak.net Sat May 27 18:03:15 2006 From: sanxiyn at codespeak.net (sanxiyn at codespeak.net) Date: Sat, 27 May 2006 18:03:15 +0200 (CEST) Subject: [pypy-svn] r27770 - pypy/dist/pypy/translator/cl Message-ID: <20060527160315.58A2F100AB@code0.codespeak.net> Author: sanxiyn Date: Sat May 27 18:03:11 2006 New Revision: 27770 Modified: pypy/dist/pypy/translator/cl/gencl.py Log: More reordering Modified: pypy/dist/pypy/translator/cl/gencl.py ============================================================================== --- pypy/dist/pypy/translator/cl/gencl.py (original) +++ pypy/dist/pypy/translator/cl/gencl.py Sat May 27 18:03:11 2006 @@ -263,53 +263,44 @@ elif len(exits) == 1: for line in self.emit_link(exits[0]): yield line - elif len(exits) > 1: - # only works in the current special case - if (len(exits) == 2 and - exits[0].exitcase == False and - exits[1].exitcase == True): - yield "(if " + clrepr(block.exitswitch, True) - yield "(progn" - for line in self.emit_link(exits[1]): - yield line - yield ") ; else" - yield "(progn" - for line in self.emit_link(exits[0]): - yield line - yield "))" - elif block.exitswitch is c_last_exception: - body = None - exceptions = {} - for exit in exits: - if exit.exitcase is None: - body = exit - else: - cls = exit.llexitcase.class_._INSTANCE - exception = self.declare_exception(cls) - exceptions[exception] = exit - for line in self.emit_link(body): + elif handle_exc: + body = None + exceptions = {} + for exit in exits: + if exit.exitcase is None: + body = exit + else: + cls = exit.llexitcase.class_._INSTANCE + exception = self.declare_exception(cls) + exceptions[exception] = exit + for line in self.emit_link(body): + yield line + yield ")" # closes the progn for the handler-case + for exception in exceptions: + yield "(%s ()" % (exception,) + for line in self.emit_link(exceptions[exception]): yield line - yield ")" # closes the progn for the handler-case - for exception in exceptions: - yield "(%s ()" % (exception,) - for line in self.emit_link(exceptions[exception]): - yield line - yield ")" - else: - # this is for the more general case. The previous special case - # shouldn't be needed but in Python 2.2 we can't tell apart - # 0 vs nil and 1 vs t :-( - for exit in exits[:-1]: - yield "(if (equalp " + clrepr(block.exitswitch, True) - yield clrepr(exit.exitcase, True) + ')' - yield "(progn" - for line in self.emit_link(exit): - yield line - yield ")" - yield "(progn ; else should be %s" % clrepr(exits[-1].exitcase, True) - for line in self.emit_link(exits[-1]): + yield ")" + elif len(exits) == 2: + assert exits[0].exitcase == False + assert exits[1].exitcase == True + yield "(if %s" % (clrepr(block.exitswitch),) + yield "(progn" + for line in self.emit_link(exits[1]): + yield line + yield ") ; else" + yield "(progn" + for line in self.emit_link(exits[0]): + yield line + yield "))" + else: + yield "(case %s" % (clrepr(block.exitswitch),) + for exit in exits: + yield "(%s" % (clrepr(exit.exitcase),) + for line in self.emit_link(exit): yield line - yield ")" * len(exits) + yield ")" + yield ")" if handle_exc: yield ")" From antocuni at codespeak.net Sat May 27 21:10:43 2006 From: antocuni at codespeak.net (antocuni at codespeak.net) Date: Sat, 27 May 2006 21:10:43 +0200 (CEST) Subject: [pypy-svn] r27774 - in pypy/dist/pypy/translator/cli: . src test Message-ID: <20060527191043.F1B06100A8@code0.codespeak.net> Author: antocuni Date: Sat May 27 21:10:23 2006 New Revision: 27774 Modified: pypy/dist/pypy/translator/cli/cts.py pypy/dist/pypy/translator/cli/database.py pypy/dist/pypy/translator/cli/metavm.py pypy/dist/pypy/translator/cli/src/pypylib.cs pypy/dist/pypy/translator/cli/test/runtest.py pypy/dist/pypy/translator/cli/test/test_runtest.py Log: Added basic string support. Modified: pypy/dist/pypy/translator/cli/cts.py ============================================================================== --- pypy/dist/pypy/translator/cli/cts.py (original) +++ pypy/dist/pypy/translator/cli/cts.py Sat May 27 21:10:23 2006 @@ -29,6 +29,7 @@ ootype.Char: 'char', ootype.UniChar: 'char', ootype.Class: 'class [mscorlib]System.Type', + ootype.String: 'string', # maps generic types to their ordinal ootype.List.SELFTYPE_T: 'class ' + (PYPY_LIST % '!0'), Modified: pypy/dist/pypy/translator/cli/database.py ============================================================================== --- pypy/dist/pypy/translator/cli/database.py (original) +++ pypy/dist/pypy/translator/cli/database.py Sat May 27 21:10:23 2006 @@ -132,6 +132,8 @@ return RecordConst(db, const) elif isinstance(const, ootype._list): return ListConst(db, const) + elif isinstance(const, ootype._string): + return StringConst(db, const) else: assert False, 'Unknown constant: %s' % const make = staticmethod(make) @@ -165,6 +167,27 @@ def init(self, ilasm): pass +class StringConst(AbstractConst): + def __init__(self, db, string): + self.db = db + self.cts = CTS(db) + self.string = string + + def __hash__(self): + return hash(self.string) + + def __eq__(self, other): + return self.string == other.string + + def get_name(self): + return 'string_literal' + + def get_type(self, include_class=True): + return self.cts.lltype_to_cts(ootype.String, include_class) + + def init(self, ilasm): + ilasm.opcode('ldstr', '"%s"' % self.string._str) + class RecordConst(AbstractConst): def __init__(self, db, record): self.db = db Modified: pypy/dist/pypy/translator/cli/metavm.py ============================================================================== --- pypy/dist/pypy/translator/cli/metavm.py (original) +++ pypy/dist/pypy/translator/cli/metavm.py Sat May 27 21:10:23 2006 @@ -73,7 +73,7 @@ for arg in args: # push parametes generator.load(arg) generator.call_method(this.concretetype, method_name) - + class _CallMethod(_Call): def render(self, generator, op): Modified: pypy/dist/pypy/translator/cli/src/pypylib.cs ============================================================================== --- pypy/dist/pypy/translator/cli/src/pypylib.cs (original) +++ pypy/dist/pypy/translator/cli/src/pypylib.cs Sat May 27 21:10:23 2006 @@ -12,6 +12,8 @@ public static string ToPython(uint x) { return x.ToString(); } public static string ToPython(long x) { return x.ToString(); } public static string ToPython(ulong x) { return x.ToString(); } + // XXX: it does not support strings containing "'". + public static string ToPython(string x) { return string.Format("'{0}'", x); } public static string ToPython(object obj) { @@ -33,7 +35,6 @@ { return t.GetConstructor(new Type[0]).Invoke(new object[0]); } - } //The public interface List must implement is defined in Modified: pypy/dist/pypy/translator/cli/test/runtest.py ============================================================================== --- pypy/dist/pypy/translator/cli/test/runtest.py (original) +++ pypy/dist/pypy/translator/cli/test/runtest.py Sat May 27 21:10:23 2006 @@ -34,7 +34,7 @@ assert res1 == res2 def format_object(TYPE, ilasm): - if isinstance(TYPE, (ootype.BuiltinType, ootype.Instance)): + if isinstance(TYPE, (ootype.BuiltinType, ootype.Instance)) and TYPE is not ootype.String: ilasm.call_method('string object::ToString()', virtual=True) elif TYPE is ootype.Void: ilasm.opcode('ldstr "None"') @@ -224,7 +224,7 @@ assert issubclass(eval(res.class_name), exception) def ll_to_string(self, s): - py.test.skip('ll_to_string not supported, yet') + return s def ll_to_list(self, l): return l Modified: pypy/dist/pypy/translator/cli/test/test_runtest.py ============================================================================== --- pypy/dist/pypy/translator/cli/test/test_runtest.py (original) +++ pypy/dist/pypy/translator/cli/test/test_runtest.py Sat May 27 21:10:23 2006 @@ -31,6 +31,12 @@ return 1, 2 assert self.interpret(fn, []) == (1, 2) + def test_string(self): + def fn(): + return 'foo' + res = self.interpret(fn, []) + assert self.ll_to_string(res) == 'foo' + def test_exception(self): def fn(): raise ValueError From arigo at codespeak.net Sun May 28 22:51:54 2006 From: arigo at codespeak.net (arigo at codespeak.net) Date: Sun, 28 May 2006 22:51:54 +0200 (CEST) Subject: [pypy-svn] r27801 - in pypy/dist/pypy/rpython: . lltypesystem Message-ID: <20060528205154.72BCC10060@code0.codespeak.net> Author: arigo Date: Sun May 28 22:51:53 2006 New Revision: 27801 Modified: pypy/dist/pypy/rpython/lltypesystem/rlist.py pypy/dist/pypy/rpython/rtyper.py Log: Fixed an exceedingly obscure bug that only showed up in test_rlist from time to time. Blame CPython! The dict lookup eats all exceptions from the user-defined __eq__... Modified: pypy/dist/pypy/rpython/lltypesystem/rlist.py ============================================================================== --- pypy/dist/pypy/rpython/lltypesystem/rlist.py (original) +++ pypy/dist/pypy/rpython/lltypesystem/rlist.py Sun May 28 22:51:53 2006 @@ -49,10 +49,10 @@ self.listitem = listitem self.list_cache = {} # setup() needs to be called to finish this initialization - self.list_builder = ListBuilder() + self.list_builder = ListBuilder(self) def _setup_repr_final(self): - self.list_builder.setup(self) + self.list_builder.setup() def null_const(self): return nullptr(self.LIST) @@ -83,12 +83,19 @@ class ListBuilder(object): """Interface to allow lazy list building by the JIT.""" - # This should not keep a reference to the RTyper, even indirectly via - # the list_repr. - - def setup(self, list_repr): + + def __init__(self, list_repr): + # This should not keep a reference to the RTyper, even indirectly via + # the list_repr. So tmp_list_repr is replaced by None in setup(). + self.tmp_list_repr = list_repr + + def setup(self): # Precompute the c_newitem and c_setitem_nonneg function pointers, # needed below. + list_repr = self.tmp_list_repr + if list_repr is None: + return # already set up + self.tmp_list_repr = None if list_repr.rtyper is None: return # only for test_rlist, which doesn't need this anyway @@ -127,8 +134,18 @@ Void) return v_result + def getlistptr(self): + list_repr = self.tmp_list_repr + if list_repr is not None: + list_repr.setup() + return list_repr.lowleveltype + else: + return self.LISTPTR + def __eq__(self, other): - return self.LISTPTR == other.LISTPTR + if not isinstance(other, ListBuilder): + return False + return self.getlistptr() == other.getlistptr() def __ne__(self, other): return not (self == other) Modified: pypy/dist/pypy/rpython/rtyper.py ============================================================================== --- pypy/dist/pypy/rpython/rtyper.py (original) +++ pypy/dist/pypy/rpython/rtyper.py Sun May 28 22:51:53 2006 @@ -139,12 +139,14 @@ try: result = self.reprs[key] except KeyError: + self.reprs[key] = None result = self.makerepr(s_obj) 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.add_pendingsetup(result) + assert result is not None # recursive getrepr()! return result def binding(self, var, default=annmodel.SomeObject()): From ale at codespeak.net Mon May 29 09:21:45 2006 From: ale at codespeak.net (ale at codespeak.net) Date: Mon, 29 May 2006 09:21:45 +0200 (CEST) Subject: [pypy-svn] r27818 - pypy/extradoc/sprintinfo/ddorf2006 Message-ID: <20060529072145.D42C41005A@code0.codespeak.net> Author: ale Date: Mon May 29 09:21:45 2006 New Revision: 27818 Modified: pypy/extradoc/sprintinfo/ddorf2006/people.txt Log: I am staying at Hotel an der Uni too Modified: pypy/extradoc/sprintinfo/ddorf2006/people.txt ============================================================================== --- pypy/extradoc/sprintinfo/ddorf2006/people.txt (original) +++ pypy/extradoc/sprintinfo/ddorf2006/people.txt Mon May 29 09:21:45 2006 @@ -18,7 +18,7 @@ Samuele Pedroni 1st - 9th Hotel an der Uni Christian Tismer 1st - 9th ? Antonio Cuni 1st - 9th cfbolz -Anders Lehmann 2nd - 9th ? +Anders Lehmann 2nd - 9th Hotel an der Uni ==================== ============== ===================== People on the following list were present at previous sprints: From ericvrp at codespeak.net Mon May 29 09:57:30 2006 From: ericvrp at codespeak.net (ericvrp at codespeak.net) Date: Mon, 29 May 2006 09:57:30 +0200 (CEST) Subject: [pypy-svn] r27822 - pypy/dist/pypy/doc Message-ID: <20060529075730.35D4710053@code0.codespeak.net> Author: ericvrp Date: Mon May 29 09:57:28 2006 New Revision: 27822 Modified: pypy/dist/pypy/doc/getting-started.txt Log: llvm-translated pypy should be created a little differently these days Modified: pypy/dist/pypy/doc/getting-started.txt ============================================================================== --- pypy/dist/pypy/doc/getting-started.txt (original) +++ pypy/dist/pypy/doc/getting-started.txt Mon May 29 09:57:28 2006 @@ -536,7 +536,7 @@ To create a standalone executable using the experimental LLVM_ compiler infrastructure:: - ./run_pypy-llvm.sh + ./translate.py --text --batch --backend=llvm --raisingop2direct_call targetpypystandalone.py .. _`start reading sources`: From ericvrp at codespeak.net Mon May 29 11:41:52 2006 From: ericvrp at codespeak.net (ericvrp at codespeak.net) Date: Mon, 29 May 2006 11:41:52 +0200 (CEST) Subject: [pypy-svn] r27829 - in pypy/dist/pypy: interpreter/test module/_pickle_support objspace/std Message-ID: <20060529094152.7884610057@code0.codespeak.net> Author: ericvrp Date: Mon May 29 11:41:51 2006 New Revision: 27829 Modified: pypy/dist/pypy/interpreter/test/test_pickle.py pypy/dist/pypy/module/_pickle_support/maker.py pypy/dist/pypy/objspace/std/itertype.py Log: sequence iterator pickling support (still need to test translation on a faster machine) Modified: pypy/dist/pypy/interpreter/test/test_pickle.py ============================================================================== --- pypy/dist/pypy/interpreter/test/test_pickle.py (original) +++ pypy/dist/pypy/interpreter/test/test_pickle.py Mon May 29 11:41:51 2006 @@ -182,12 +182,15 @@ tupleiterator that is why you will find no test_pickle_listiter nor test_pickle_tupleiter here, just this test. ''' - skip("work in progress") import pickle - liter = iter([]) + liter = iter([3,9,6,12,15,17,19,111]) + liter.next() pckl = pickle.dumps(liter) result = pickle.loads(pckl) - assert liter == result + liter.next() + result.next() + assert len(liter) == 6 + assert list(liter) == list(result) def test_pickle_dictiter(self): import pickle Modified: pypy/dist/pypy/module/_pickle_support/maker.py ============================================================================== --- pypy/dist/pypy/module/_pickle_support/maker.py (original) +++ pypy/dist/pypy/module/_pickle_support/maker.py Mon May 29 11:41:51 2006 @@ -6,7 +6,7 @@ from pypy.interpreter.argument import Arguments from pypy.interpreter.baseobjspace import ObjSpace, W_Root from pypy.objspace.std.dicttype import dictiter_typedef -from pypy.objspace.std.itertype import iter_typedef as seqiter_typedef +from pypy.objspace.std.iterobject import W_SeqIterObject #note: for now we don't use the actual value when creating the Cell. @@ -41,13 +41,5 @@ return space.iter(w_lis) dictiter_surrogate_new.unwrap_spec = [ObjSpace, W_Root] -#XXX this doesn't work yet -def seqiter_new(space, w_seqitertype, __args__): - raise Exception('No seqiter_new (pickle support) yet') - print "seqiter_new here 1)", space, __args__ - w_type = space.gettypeobject(seqiter_typedef) - print "seqiter_new here 2)", w_type - a = space.call_args(w_type, __args__) - print "seqiter_new here 3)", a - return a -seqiter_new.unwrap_spec = [ObjSpace, W_Root, Arguments] +def seqiter_new(space, w_seq, w_index): + return W_SeqIterObject(w_seq, space.int_w(w_index)) Modified: pypy/dist/pypy/objspace/std/itertype.py ============================================================================== --- pypy/dist/pypy/objspace/std/itertype.py (original) +++ pypy/dist/pypy/objspace/std/itertype.py Mon May 29 11:41:51 2006 @@ -1,13 +1,30 @@ from pypy.objspace.std.stdtypedef import * # ____________________________________________________________ + +def descr_seqiter__reduce__(w_self, space): + """ + XXX to do: remove this __reduce__ method and do + a registration with copy_reg, instead. + """ + from pypy.interpreter.mixedmodule import MixedModule + w_mod = space.getbuiltinmodule('_pickle_support') + mod = space.interp_w(MixedModule, w_mod) + new_inst = mod.get('seqiter_new') + tup = [w_self.w_seq, space.wrap(w_self.index)] + return space.newtuple([new_inst, space.newtuple(tup)]) + +# ____________________________________________________________ iter_typedef = StdTypeDef("sequenceiterator", __doc__ = '''iter(collection) -> iterator iter(callable, sentinel) -> iterator Get an iterator from an object. In the first form, the argument must supply its own iterator, or be a sequence. -In the second form, the callable is called until it returns the sentinel.''' +In the second form, the callable is called until it returns the sentinel.''', + + __reduce__ = gateway.interp2app(descr_seqiter__reduce__, + unwrap_spec=[gateway.W_Root, gateway.ObjSpace]), ) reverse_iter_typedef = StdTypeDef("reversesequenceiterator", From arigo at codespeak.net Mon May 29 12:10:42 2006 From: arigo at codespeak.net (arigo at codespeak.net) Date: Mon, 29 May 2006 12:10:42 +0200 (CEST) Subject: [pypy-svn] r27832 - pypy/extradoc/talk/dls2006 Message-ID: <20060529101042.360E210061@code0.codespeak.net> Author: arigo Date: Mon May 29 12:10:35 2006 New Revision: 27832 Modified: pypy/extradoc/talk/dls2006/draft.txt Log: Added the Flow Object Space bit. Modified: pypy/extradoc/talk/dls2006/draft.txt ============================================================================== --- pypy/extradoc/talk/dls2006/draft.txt (original) +++ pypy/extradoc/talk/dls2006/draft.txt Mon May 29 12:10:35 2006 @@ -80,9 +80,10 @@ We shortly describe the architecture of PyPy in `section 2`_. In `section 3`_ we describe our approach of varying the type systems at various levels of the translation. `Section 4`_ gives an overview of -the type inference engine we developed. We present experimental results in -`section 5`_ and future work directions in `section 6`_. In `section 7`_ -we compare with related work, and finally we conclude in `section 8`_. +the type inference engine we developed (and can be read independently +from section 3.) We present experimental results in `section 5`_ and +future work directions in `section 6`_. In `section 7`_ we compare with +related work, and finally we conclude in `section 8`_. .. _`section 2`: @@ -145,19 +146,18 @@ ``[figure: flow graph and annotator, e.g. part of doc/image/translation.*]`` 1. We take as input RPython functions [#]_, and convert them to control flow - graphs -- a structure amenable to analysis. These flow graphs contain + graphs - a structure amenable to analysis. These flow graphs contain polymorphic operations only: in Python, almost all operations are - dynamically overloaded by type, whereas the absence of macros means - that the control flow is static. + dynamically overloaded by type. .. [#] The input to our translation chain are indeed loaded - runtime function objects, not source code or ASTs, this + runtime function objects, not source code or ASTs. This allows us to use unrestricted python for meta-programming purposes at load time, in a seemingly staged programming approach, - in which the whole of the source program as Python program + in which the whole of the source program - as Python program - produces the RPython program input to the tool-chain as the - object graph loaded in memory, and in particular the relevant - functions. + object graph loaded in memory. This includes both the relevant + functions and prebuilt data. 2. We perform type inference on the control flow graphs. At this stage, types inferred are part of the type system which is the very definition @@ -217,7 +217,7 @@ continuation-passing style (CPS) [I'm not sure our transformation can be classified as classical CPS, although there are known similar techniques but the terminology is quite confused] that allows us to use coroutines without giving up the ability to generate fully ANSI C code. (This will -be the subject of another paper.) +be the subject of another paper.) [mention exception transformer too] Finally, currently under development is a variant of the very first transformation step, for use when targeting higher-level, @@ -249,7 +249,7 @@ but that need to be decomposed into several operations in the target (lower-level) graphs. In some cases, the equivalent functionality requires more than a couple of operations: a single operation must be -replaced by a call to whole new code -- functions and classes that serve +replaced by a call to whole new code - functions and classes that serve as helpers. An example of this is the ``malloc`` operation for the GC transformer. Another example is the ``list.append()`` method, which is atomic for Python or RPython programs, but needs to be replaced in @@ -258,7 +258,7 @@ This means that in addition to transforming the existing graphs, each transformation step also needs to insert new functions into the forest. A key feature of our approach is that we can write such "system-level" -code -- relevant only to a particular transformation -- in plain Python +code - relevant only to a particular transformation - in plain Python as well: .. topic:: Figure 1 - a helper to implement ``list.append()`` @@ -317,7 +317,7 @@ list and dictionary operations, instance and class attribute accesses, many string processing methods, a good subset of all Python built-in functions... Compared to other approaches [e.g. Squeak], we do not try -to minimize the number of primitives -- at least not at the source +to minimize the number of primitives - at least not at the source level. It is fine to have many primitives at any high enough level, because they can all be implemented at the next lower level in a way that makes sense to that level. The key reason why this is not @@ -406,21 +406,156 @@ ============================================================ -The various analyses used -- from type inference to lifetime analysis -- +The various analyses used - from type inference to lifetime analysis - are generally formulated as `abstract interpretation`_. While this approach is known to be less efficient than more tailored algorithms like constraint-based type inference, we gain in freedom, controllability and simplicity. This proved essential in our overall approach: as described in `section 3`_, we need to perform type -inference with many different type systems, the details of which are -still evolving. We mitigate the potential efficiency problem by wise -choices and compromises for the domain used; the foremost example of -this is that our RPython type inference performs almost no automatic -specialization of functions. We achieved enough precision for our -purpose, though, and in order to use the PyPy Standard Interpreter as -the source RPython program we had to add only a few explicit -specialization annotations manually. +inference with many different type systems, the details of which have +evolved along the road. +We mitigate the potential efficiency problem by wise choices and +compromises for the domain used; the foremost example of this is that +our RPython type inference performs almost no automatic specialization +of functions. We achieved enough precision for our purpose, though. + +In the sequel, we give a more precise description of this process and +justify our claim that good performance and enough precision can be +achieved - at least in some contexts - without giving up the naive but +flexible approach. + + +Building control flow graphs +---------------------------- + +As described in the overview of `the translation process`_, the +front-end of the translation tool-chain works in two phases: it first +builds control flow graphs from Python functions, and then performs +whole-program type inference on these graphs. + +Remember that building the control flow graphs is not done, as one might +first expect, by following a function at the syntactic level. Instead, +the whole program is imported in a normal Python interpreter; the full +Python language is used at this point as a kind of preprocessor with +meta-programming capabilities. Once the program is imported, the object +data in memory consists of Python function objects in bytecode format, +and any other kind of objects created at import-time, like class +objects, prebuilt instances of those, prebuilt tables, and so on. Note +that these objects have typically no text representation any more; for +example, cyclic data structures may have been built at this point. The +translation tool-chain first turns these function objects into in-memory +control flow graphs which contain direct references to the prebuilt data +objects, and then handles and transforms these graphs. We found +in-process debugging sufficient and did not implement dumping of any +intermediate step to disk. + +The actual transformation from function objects - i.e. bytecode - to +flow graph is performed by the Flow Object Space, a short but generic +plug-in component for the Python interpreter of PyPy. The architecture +of our Python interpreter is shown in figure 3. + +.. topic:: Figure 3 - the interpreter and object spaces + + +------------------------------------------------------+ + | forest of bytecode objects from the application | + +------------------------------------------------------+ + | Python bytecode interpreter | + +--------------------------------+---------------------+ + | Standard Object Space | Flow Object Space | + +--------------------------------+---------------------+ + +Note that the left column, i.e. the bytecode interpreter and the +Standard Object Space, form the full Python interpreter of PyPy. It is +an RPython program, and the whole purpose of the translation process is +to accept this as *input*, and translate it to an efficient form. Its +architecture is not relevant to the way it is translated. + +However, the bytecode interpreter plays a double role, at two different +levels. The so-called Object Spaces are *domains* in the abstract +interpretation terminology. By design, we cleanly separated these +domains from the bytecode interpreter core; the latter is only +responsible for decoding the bytecodes of an application and emulating +the corresponding stack machine. It treats all actual application-level +objects as black boxes, and dispatches all operations on them to the +Object Space. The Standard Object Space is a concrete domain, in which +objects are the concrete Python objects of the various built-in types: +lists, dictionaries, and so on. By opposition, the Flow Object Space is +really an abstract domain. It handles objects that are placeholders. +Its lattice order is shown in figure 4. + +:: + + [figure 4: Variable + + / | \ \ + / | \ \ + / | \ \ + Constant(1) ... Constant(n) ... Constant([1,2,3]) ... Constant() ... + ] + +This order is extremely simple, because most actual analysis is delayed +to the next phase, the type inference engine. The objects are either +*Variables*, which are pure placeholders for entierely unknown values, +or *Constants* with a concrete Python object as value. The order places +Variable as the top, and keeps all *Constants* unordered. Thus if two +different constants merge during abstract interpretation, we immediately +widen them to Variable. + +In conjunction with the Flow Object Space, the bytecode interpreter of +PyPy thus performs abstract interpretation of Python bytecodes from the +application. [#]_ In this case, the bytecodes in question come from the +RPython application that we would like to translate. + +.. [#] Note that this process uses the *unmodified* bytecode + interpreter. This means that it is independent of most language + details. Changes in syntax or in bytecode format or opcode semantics + only need to be implemented once, in the bytecode interpreter. In + effect, the Flow Object Space enables an interpreter for *any* language + to work as a front-end for the rest of the tool-chain. + +The Flow Object Space records all operations that the bytecode +interpreter "would like" to do between the placeholder objects. It +records them into basic block objects that will eventually be part of +the control flow graph of the whole function. The recorded operations +take Variables and Constants as argument, and produce new Variables as +results. The Constants serve two purposes: they are a way to introduce +constant values into the flow graphs - these values may be arbitrarily +complex objects, not just primitives - and they allow basic constant +propagation. [#]_ + +.. [#] This is useful at this level for some constructs of the bytecode + interpreter, which can temporarily wrap internal values and push them + onto the regular value stack among the other application-level objects. + We need to be able to unwrap them again later. + +In the flow graph, branching occurs when the bytecode interpreter tries +to inspect the truth value of placeholder objects, as it would in +response to conditional jump opcodes or other more complicated opcodes: +at this point, the Flow Object Space starts two new basic blocks and - +with a technique akin to continuations - tricks the interpreter into +following both branches, one after the other. Additionally, the +bytecode interpreter sends simple positional signals that allow the Flow +Object Space to detect when control paths merge, or when loops close. +In this way, abstract interpretation quickly terminates and the recorded +operations form a graph, which is the control flow graph of the original +bytecode. + +While the Flow Object Space is quite a short piece of code - its core +functionality holds in 300 lines - the detail of the interactions +sketched above is not entierely straightforward; we refer the reader to +`[D]`_ for more information. Figure 5 shows the control flow graph +obtained for a simple function (this is a screenshot from our graph +viewer, used for debugging; basic block placement is performed by +Graphviz_). + +:: + + [figure 5: insert a nice pygame screenshot] + + +Type inference +-------------- XXX @@ -469,9 +604,11 @@ XXX +.. _`[D]`: http://codespeak.net/pypy/dist/pypy/doc/dynamic-language-translation.html .. _`[S]`: http://codespeak.net/pypy/dist/pypy/doc/architecture.html#the-standard-interpreter .. _`[T]`: http://codespeak.net/pypy/dist/pypy/doc/translation.html .. _`abstract interpretation`: http://en.wikipedia.org/wiki/Abstract_interpretation +.. _Graphviz: http://www.graphviz.org/ .. http://www.cs.jhu.edu/~scott/pll/constraints.html page to the reference /recent result for constraint-based type inference From ericvrp at codespeak.net Mon May 29 12:13:26 2006 From: ericvrp at codespeak.net (ericvrp at codespeak.net) Date: Mon, 29 May 2006 12:13:26 +0200 (CEST) Subject: [pypy-svn] r27833 - in pypy/dist/pypy: interpreter/test module/_pickle_support objspace/std Message-ID: <20060529101326.6CA5B10068@code0.codespeak.net> Author: ericvrp Date: Mon May 29 12:13:22 2006 New Revision: 27833 Modified: pypy/dist/pypy/interpreter/test/test_pickle.py pypy/dist/pypy/module/_pickle_support/__init__.py pypy/dist/pypy/module/_pickle_support/maker.py pypy/dist/pypy/objspace/std/itertype.py Log: Added pickling support for reverse sequence iterator Modified: pypy/dist/pypy/interpreter/test/test_pickle.py ============================================================================== --- pypy/dist/pypy/interpreter/test/test_pickle.py (original) +++ pypy/dist/pypy/interpreter/test/test_pickle.py Mon May 29 12:13:22 2006 @@ -189,9 +189,22 @@ result = pickle.loads(pckl) liter.next() result.next() + assert type(liter) is type(result) assert len(liter) == 6 assert list(liter) == list(result) - + + def test_pickle_reversesequenceiter(self): + import pickle + liter = reversed([3,9,6,12,15,17,19,111]) + liter.next() + pckl = pickle.dumps(liter) + result = pickle.loads(pckl) + liter.next() + result.next() + assert type(liter) is type(result) + assert len(liter) == 6 + assert list(liter) == list(result) + def test_pickle_dictiter(self): import pickle tdict = {'2':2, '3':3, '5':5} @@ -224,16 +237,6 @@ assert type(riter) is type(result) assert list(result) == [2,3,4] - def test_pickle_reversed_iterator(self): - import pickle - i = reversed(xrange(5)) - i.next() - i.next() - pckl = pickle.dumps(i) - result = pickle.loads(pckl) - assert type(i) is type(result) - assert list(result) == [2,1,0] - def test_pickle_generator(self): skip("work in progress") import pickle Modified: pypy/dist/pypy/module/_pickle_support/__init__.py ============================================================================== --- pypy/dist/pypy/module/_pickle_support/__init__.py (original) +++ pypy/dist/pypy/module/_pickle_support/__init__.py Mon May 29 12:13:22 2006 @@ -14,4 +14,5 @@ 'method_new' : 'maker.method_new', 'dictiter_surrogate_new' : 'maker.dictiter_surrogate_new', 'seqiter_new' : 'maker.seqiter_new', + 'reverseseqiter_new' : 'maker.reverseseqiter_new', } Modified: pypy/dist/pypy/module/_pickle_support/maker.py ============================================================================== --- pypy/dist/pypy/module/_pickle_support/maker.py (original) +++ pypy/dist/pypy/module/_pickle_support/maker.py Mon May 29 12:13:22 2006 @@ -6,7 +6,7 @@ from pypy.interpreter.argument import Arguments from pypy.interpreter.baseobjspace import ObjSpace, W_Root from pypy.objspace.std.dicttype import dictiter_typedef -from pypy.objspace.std.iterobject import W_SeqIterObject +from pypy.objspace.std.iterobject import W_SeqIterObject, W_ReverseSeqIterObject #note: for now we don't use the actual value when creating the Cell. @@ -43,3 +43,8 @@ def seqiter_new(space, w_seq, w_index): return W_SeqIterObject(w_seq, space.int_w(w_index)) + +def reverseseqiter_new(space, w_seq, w_index): + w_len = space.len(w_seq) + index = space.int_w(w_index) - space.int_w(w_len) + return W_ReverseSeqIterObject(space, w_seq, index) Modified: pypy/dist/pypy/objspace/std/itertype.py ============================================================================== --- pypy/dist/pypy/objspace/std/itertype.py (original) +++ pypy/dist/pypy/objspace/std/itertype.py Mon May 29 12:13:22 2006 @@ -15,6 +15,20 @@ return space.newtuple([new_inst, space.newtuple(tup)]) # ____________________________________________________________ + +def descr_reverseseqiter__reduce__(w_self, space): + """ + XXX to do: remove this __reduce__ method and do + a registration with copy_reg, instead. + """ + from pypy.interpreter.mixedmodule import MixedModule + w_mod = space.getbuiltinmodule('_pickle_support') + mod = space.interp_w(MixedModule, w_mod) + new_inst = mod.get('reverseseqiter_new') + tup = [w_self.w_seq, space.wrap(w_self.index)] + return space.newtuple([new_inst, space.newtuple(tup)]) + +# ____________________________________________________________ iter_typedef = StdTypeDef("sequenceiterator", __doc__ = '''iter(collection) -> iterator iter(callable, sentinel) -> iterator @@ -28,4 +42,7 @@ ) reverse_iter_typedef = StdTypeDef("reversesequenceiterator", + + __reduce__ = gateway.interp2app(descr_reverseseqiter__reduce__, + unwrap_spec=[gateway.W_Root, gateway.ObjSpace]), ) From arigo at codespeak.net Mon May 29 12:24:10 2006 From: arigo at codespeak.net (arigo at codespeak.net) Date: Mon, 29 May 2006 12:24:10 +0200 (CEST) Subject: [pypy-svn] r27834 - pypy/extradoc/talk/dls2006 Message-ID: <20060529102410.D55A51006D@code0.codespeak.net> Author: arigo Date: Mon May 29 12:24:09 2006 New Revision: 27834 Modified: pypy/extradoc/talk/dls2006/draft.txt Log: Move the flow graph screenshot to the beginning of the subsection. Modified: pypy/extradoc/talk/dls2006/draft.txt ============================================================================== --- pypy/extradoc/talk/dls2006/draft.txt (original) +++ pypy/extradoc/talk/dls2006/draft.txt Mon May 29 12:24:09 2006 @@ -446,16 +446,24 @@ example, cyclic data structures may have been built at this point. The translation tool-chain first turns these function objects into in-memory control flow graphs which contain direct references to the prebuilt data -objects, and then handles and transforms these graphs. We found -in-process debugging sufficient and did not implement dumping of any -intermediate step to disk. +objects, and then handles and transforms these graphs. + +We found in-process debugging sufficient and did not implement dumping +of any intermediate step to disk. Figure 3 shows the control flow graph +obtained for a simple function - this is a screenshot from our graph +viewer, used for debugging; basic block placement is performed by +Graphviz_. + +:: + + [figure 3: insert a nice pygame screenshot] The actual transformation from function objects - i.e. bytecode - to flow graph is performed by the Flow Object Space, a short but generic plug-in component for the Python interpreter of PyPy. The architecture -of our Python interpreter is shown in figure 3. +of our Python interpreter is shown in figure 4. -.. topic:: Figure 3 - the interpreter and object spaces +.. topic:: Figure 4 - the interpreter and object spaces +------------------------------------------------------+ | forest of bytecode objects from the application | @@ -482,11 +490,11 @@ objects are the concrete Python objects of the various built-in types: lists, dictionaries, and so on. By opposition, the Flow Object Space is really an abstract domain. It handles objects that are placeholders. -Its lattice order is shown in figure 4. +Its lattice order is shown in figure 5. :: - [figure 4: Variable + [figure 5: Variable / | \ \ / | \ \ @@ -544,14 +552,8 @@ While the Flow Object Space is quite a short piece of code - its core functionality holds in 300 lines - the detail of the interactions sketched above is not entierely straightforward; we refer the reader to -`[D]`_ for more information. Figure 5 shows the control flow graph -obtained for a simple function (this is a screenshot from our graph -viewer, used for debugging; basic block placement is performed by -Graphviz_). - -:: +`[D]`_ for more information. - [figure 5: insert a nice pygame screenshot] Type inference From ericvrp at codespeak.net Mon May 29 12:29:52 2006 From: ericvrp at codespeak.net (ericvrp at codespeak.net) Date: Mon, 29 May 2006 12:29:52 +0200 (CEST) Subject: [pypy-svn] r27836 - pypy/dist/pypy/interpreter/test Message-ID: <20060529102952.9C9CC1006D@code0.codespeak.net> Author: ericvrp Date: Mon May 29 12:29:51 2006 New Revision: 27836 Modified: pypy/dist/pypy/interpreter/test/test_pickle.py Log: update enum pickle test Modified: pypy/dist/pypy/interpreter/test/test_pickle.py ============================================================================== --- pypy/dist/pypy/interpreter/test/test_pickle.py (original) +++ pypy/dist/pypy/interpreter/test/test_pickle.py Mon May 29 12:29:51 2006 @@ -220,13 +220,13 @@ e = enumerate(range(10)) e.next() e.next() - e._iter= 42 #XXX HACK, because we have no sequence/dict iterator yet pckl = pickle.dumps(e) result = pickle.loads(pckl) + e.next() + result.next() assert type(e) is type(result) - assert e._iter == result._iter #change when _iter is an iter(..) again - assert e._index == result._index - + assert list(e) == list(result) + def test_pickle_xrangeiter(self): import pickle riter = iter(xrange(5)) From ericvrp at codespeak.net Mon May 29 14:36:47 2006 From: ericvrp at codespeak.net (ericvrp at codespeak.net) Date: Mon, 29 May 2006 14:36:47 +0200 (CEST) Subject: [pypy-svn] r27842 - pypy/dist/pypy/translator/goal Message-ID: <20060529123647.EB03C10036@code0.codespeak.net> Author: ericvrp Date: Mon May 29 14:36:47 2006 New Revision: 27842 Removed: pypy/dist/pypy/translator/goal/run_pypy-llvm.sh Log: this tiny script is no longer required From ericvrp at codespeak.net Mon May 29 14:38:59 2006 From: ericvrp at codespeak.net (ericvrp at codespeak.net) Date: Mon, 29 May 2006 14:38:59 +0200 (CEST) Subject: [pypy-svn] r27844 - in pypy/dist/pypy: interpreter interpreter/test module/_pickle_support Message-ID: <20060529123859.B095A10050@code0.codespeak.net> Author: ericvrp Date: Mon May 29 14:38:57 2006 New Revision: 27844 Modified: pypy/dist/pypy/interpreter/pyframe.py pypy/dist/pypy/interpreter/test/test_pickle.py pypy/dist/pypy/interpreter/typedef.py pypy/dist/pypy/module/_pickle_support/__init__.py pypy/dist/pypy/module/_pickle_support/maker.py Log: * beginning of frame pickling * improved frame pickling test * fix for minor typo Modified: pypy/dist/pypy/interpreter/pyframe.py ============================================================================== --- pypy/dist/pypy/interpreter/pyframe.py (original) +++ pypy/dist/pypy/interpreter/pyframe.py Mon May 29 14:38:57 2006 @@ -51,7 +51,7 @@ self.valuestack = Stack() self.blockstack = Stack() self.last_exception = None - self.next_instr = r_uint(0) # Force it unsigned for performace reasons. + self.next_instr = r_uint(0) # Force it unsigned for performance reasons. self.builtin = space.builtin.pick_builtin(w_globals) # regular functions always have CO_OPTIMIZED and CO_NEWLOCALS. # class bodies only have CO_NEWLOCALS. @@ -66,7 +66,20 @@ self.instr_lb = 0 self.instr_ub = -1 self.instr_prev = -1; - + + def descr__reduce__(self, space): + raise Exception('frame pickling is work in progress') + from pypy.interpreter.mixedmodule import MixedModule + w_mod = space.getbuiltinmodule('_pickle_support') + mod = space.interp_w(MixedModule, w_mod) + new_inst = mod.get('frame_new') + w = space.wrap + tup = [ + w(self.pycode), + self.w_globals, + ] + return space.newtuple([new_inst, space.newtuple(tup)]) + def hide(self): return self.pycode.hidden_applevel Modified: pypy/dist/pypy/interpreter/test/test_pickle.py ============================================================================== --- pypy/dist/pypy/interpreter/test/test_pickle.py (original) +++ pypy/dist/pypy/interpreter/test/test_pickle.py Mon May 29 14:38:57 2006 @@ -73,6 +73,10 @@ assert not (cell != result) def test_pickle_frame(self): + ''' + >>>> dir(frame) + ['__class__', '__delattr__', '__doc__', '__getattribute__', '__hash__', '__init__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__str__', 'f_back', 'f_builtins', 'f_code', 'f_exc_traceback', 'f_exc_type', 'f_exc_value', 'f_globals', 'f_lasti', 'f_lineno', 'f_locals', 'f_restricted', 'f_trace'] + ''' skip("work in progress") from sys import exc_info def f(): @@ -85,8 +89,22 @@ frame = f() pckl = pickle.dumps(frame) result = pickle.loads(pckl) - assert frame == result - + assert type(frame) is type(result) + assert dir(frame) == dir(result) + assert frame.__doc__ == result.__doc__ + assert type(frame.f_back) is type(result.f_back) + assert frame.f_builtins is result.f_builtins + assert frame.f_code is result.f_code + assert frame.f_exc_traceback is result.f_exc_traceback + assert frame.f_exc_type is result.f_exc_type + assert frame.f_exc_value is result.f_exc_value + assert frame.f_globals is result.f_globals + assert frame.f_lasti == result.f_lasti + assert frame.f_lineno == result.f_lineno + assert list(frame.f_locals) == list(result.f_locals) + assert frame.f_restricted is result.f_restricted + assert frame.f_trace is result.f_trace + def test_pickle_traceback(self): skip("work in progress") def f(): @@ -238,7 +256,7 @@ assert list(result) == [2,3,4] def test_pickle_generator(self): - skip("work in progress") + skip("work in progress (implement after frame pickling)") import pickle def giveme(n): x = 0 Modified: pypy/dist/pypy/interpreter/typedef.py ============================================================================== --- pypy/dist/pypy/interpreter/typedef.py (original) +++ pypy/dist/pypy/interpreter/typedef.py Mon May 29 14:38:57 2006 @@ -521,6 +521,8 @@ ) PyFrame.typedef = TypeDef('frame', + __reduce__ = interp2app(PyFrame.descr__reduce__, + unwrap_spec=['self', ObjSpace]), f_builtins = GetSetProperty(PyFrame.fget_f_builtins), f_lineno = GetSetProperty(PyFrame.fget_f_lineno, PyFrame.fset_f_lineno), f_back = GetSetProperty(PyFrame.fget_f_back), Modified: pypy/dist/pypy/module/_pickle_support/__init__.py ============================================================================== --- pypy/dist/pypy/module/_pickle_support/__init__.py (original) +++ pypy/dist/pypy/module/_pickle_support/__init__.py Mon May 29 14:38:57 2006 @@ -15,4 +15,5 @@ 'dictiter_surrogate_new' : 'maker.dictiter_surrogate_new', 'seqiter_new' : 'maker.seqiter_new', 'reverseseqiter_new' : 'maker.reverseseqiter_new', + 'frame_new' : 'maker.frame_new', } Modified: pypy/dist/pypy/module/_pickle_support/maker.py ============================================================================== --- pypy/dist/pypy/module/_pickle_support/maker.py (original) +++ pypy/dist/pypy/module/_pickle_support/maker.py Mon May 29 14:38:57 2006 @@ -2,6 +2,7 @@ from pypy.interpreter.pycode import PyCode from pypy.interpreter.function import Function, Method from pypy.interpreter.module import Module +from pypy.interpreter.pyframe import PyFrame from pypy.rpython.objectmodel import instantiate from pypy.interpreter.argument import Arguments from pypy.interpreter.baseobjspace import ObjSpace, W_Root @@ -48,3 +49,7 @@ w_len = space.len(w_seq) index = space.int_w(w_index) - space.int_w(w_len) return W_ReverseSeqIterObject(space, w_seq, index) + +def frame_new(space, w_pycode, w_globals): + new_frame = PyFrame(space, w_pycode, w_globals, None) + return space.wrap(new_frame) From stephan at codespeak.net Mon May 29 15:09:01 2006 From: stephan at codespeak.net (stephan at codespeak.net) Date: Mon, 29 May 2006 15:09:01 +0200 (CEST) Subject: [pypy-svn] r27846 - pypy/dist/pypy/module/stackless/test Message-ID: <20060529130901.B8B8110036@code0.codespeak.net> Author: stephan Date: Mon May 29 15:08:59 2006 New Revision: 27846 Added: pypy/dist/pypy/module/stackless/test/stack4.py (contents, props changed) Modified: pypy/dist/pypy/module/stackless/test/stackless_.py Log: still not working python stackless impl. The 'stack4.py' shows a test that concentrates on exactly one feature (in this case: channel.close()). There should be more tests in this manner... Added: pypy/dist/pypy/module/stackless/test/stack4.py ============================================================================== --- (empty file) +++ pypy/dist/pypy/module/stackless/test/stack4.py Mon May 29 15:08:59 2006 @@ -0,0 +1,40 @@ +""" +this test shows what happens, when trying to use an already closed channel +""" + +import sys +import stackless +if hasattr(stackless,'coroutine'): + import stackless_ as stackless + +def f(outchan): + v = 1 + print 'f sending',v + outchan.send(v) + print 'f successfully sended',v + v = 2 + print 'f sending',v + try: + outchan.send(v) + print 'f successfully sended',v + except StopIteration: + print 'f got StopIteration' + + +def g(inchan): + print 'g before receiving' + v = inchan.receive() + print 'g received (just before closing)', v + inchan.close() + print 'g after closing channel' + try: + print 'g before receiving' + v = inchan.receive() + except StopIteration: + print 'g got StopIteration from receiving' + + +chan = stackless.channel() +t1 = stackless.tasklet(f)(chan) +t2 = stackless.tasklet(g)(chan) +stackless.run() Modified: pypy/dist/pypy/module/stackless/test/stackless_.py ============================================================================== --- pypy/dist/pypy/module/stackless/test/stackless_.py (original) +++ pypy/dist/pypy/module/stackless/test/stackless_.py Mon May 29 15:08:59 2006 @@ -23,6 +23,10 @@ last_thread_id = 0 +def restore_exception(etype, value, stack): + """until I find out how to restore an exception on python level""" + raise value + class TaskletProxy(object): def __init__(self, coro): self.alive = False @@ -71,6 +75,13 @@ traceback = None type = None value = None + def __init__(self,etype=None, value=None, traceback=None): + self.type = etype + self.value = value + self.traceback = traceback + + def _explode(self): + restore_exception(self.type, self.value, self.traceback) # channel: see below @@ -154,6 +165,8 @@ # end interface +# implicit scheduler + def _next(): c = getcurrent() if c.next is c: @@ -211,6 +224,8 @@ print c, print ']' +# end implicit scheduler + main_tasklet = None main_coroutine = None @@ -241,13 +256,6 @@ """ schedule() -note = """ -I don't see why coro_reg is needed. -tasklets should ideally inherit from coroutine. -This will create unwanted attributes, but they will -go away when we port this to interp-leve. -""" - def getcurrent(): """ getcurrent() -- return the currently executing tasklet. @@ -280,6 +288,9 @@ nt.switch() #print 'schedule: after switch', #_print_queue() + curr = getcurrent() + if type(curr.tempval) is bomb: + raise curr.tempval._explode() if retval is None: return getcurrent() else: @@ -627,6 +638,8 @@ the runnables list. The above policy can be changed by setting channel flags. """ + if self.closing: + raise StopIteration if self.balance > 0: # Receiving 1 wt = self.queue.popleft() retval = wt.tempval @@ -653,6 +666,8 @@ be activated immediately, and the sender is put at the end of the runnables list. """ + if self.closing: + raise StopIteration ct = getcurrent() if ct.tempval is not None: print 'THERE IS STILL SOME CHANNEL SEND VALUE',ct.tempval @@ -676,7 +691,8 @@ channel. exc must be a subclass of Exception. Behavior is like channel.send, but that the receiver gets an exception. """ - pass + b = bomb(exc, value) + self.send(bomb) ## needed def send_sequence(self, value): @@ -687,7 +703,8 @@ be activated immediately, and the sender is put at the end of the runnables list. """ - pass + for item in value: + self.send(item) __init() From arigo at codespeak.net Mon May 29 15:10:08 2006 From: arigo at codespeak.net (arigo at codespeak.net) Date: Mon, 29 May 2006 15:10:08 +0200 (CEST) Subject: [pypy-svn] r27847 - in pypy/extradoc/talk/dls2006: . image Message-ID: <20060529131008.2FF4910057@code0.codespeak.net> Author: arigo Date: Mon May 29 15:10:06 2006 New Revision: 27847 Added: pypy/extradoc/talk/dls2006/image/ (props changed) pypy/extradoc/talk/dls2006/image/lattice1.dot - copied unchanged from r27793, pypy/dist/pypy/doc/image/lattice1.dot pypy/extradoc/talk/dls2006/image/lattice2.dot - copied, changed from r27793, pypy/dist/pypy/doc/image/lattice2.dot Modified: pypy/extradoc/talk/dls2006/ (props changed) pypy/extradoc/talk/dls2006/draft.txt Log: The annotator part of the DLS paper. Modified: pypy/extradoc/talk/dls2006/draft.txt ============================================================================== --- pypy/extradoc/talk/dls2006/draft.txt (original) +++ pypy/extradoc/talk/dls2006/draft.txt Mon May 29 15:10:06 2006 @@ -426,6 +426,8 @@ flexible approach. +.. _`Flow Object Space`: + Building control flow graphs ---------------------------- @@ -549,17 +551,292 @@ operations form a graph, which is the control flow graph of the original bytecode. +Note that we produce flow graphs in Static Single Information (SSI) +form, an extension of Static Single Assignment (SSA_): each variable is +only used in exactly one basic block. All variables that are not dead +at the end of a basic block are explicitly carried over to the next +block and renamed. + While the Flow Object Space is quite a short piece of code - its core functionality holds in 300 lines - the detail of the interactions sketched above is not entierely straightforward; we refer the reader to `[D]`_ for more information. - Type inference -------------- -XXX +The type inference engine, which we call the *annotator*, is the central +component of the front-end part of the translation process. Given a +program considered as a family of control flow graphs, the annotator +assigns to each variable of each graph a so-called *annotation*, which +describes the possible run-time objects that this variable can contain. +Following usual terminology, we will call such annotations *types* - not +to be confused with the Python notion of the concrete type of an object. +An annotation is a set of possible values, and such a set is not always +the set of all objects of a specific Python type. + +Here is a simplified, static model of how the annotator works. It can +be considered as taking as input a finite family of functions calling +each other, and working on the control flow graphs of each of these +functions as built by the `Flow Object Space`_. Additionally, for a +particular "entry point" function, the annotator is provided with +user-specified types for the function's arguments. + +The goal of the annotator is to find the most precise type that can be +given to each variable of all control flow graphs while respecting the +constraints imposed by the operations in which these variables are +involved. + +More precisely, it is usually possible to deduce information about the +result variable of an operation given information about its arguments. +For example, we can say that the addition of two integers must be an +integer. Most programming languages have this property. However, +Python -- like many languages not specifically designed with type +inference in mind -- does not possess a type system that allows much +useful information to be derived about variables based on how they are +*used*; only on how they were *produced*. For example, a number of very +different built-in types can be involved in an addition; the meaning of +the addition and the type of the result depends on the type of the input +arguments. Merely knowing that a variable will be used in an addition +does not give much information per se. For this reason, our annotator +works by flowing types forward, operation after operation, i.e. by +performing abstract interpretation of the flow graphs. In a sense, it +is a more naive approach than the one taken by type systems specifically +designed to enable more advanced inference algorithms. For example, +`Hindley-Milner`_ type inference works in an inside-out direction, by +starting from individual operations and propagating type constraints +outwards. + +Naturally, simply propagating types forward requires the use of a fixed +point algorithm in the presence of loops in the flow graphs or in the +inter-procedural call graph. Indeed, we flow types forward from the +beginning of the entry point function into each basic block, operation +after operation, and follow all calls recursively. During this process, +each variable along the way gets a type. In various cases, e.g. when we +close a loop, the previously assigned types can be found to be too +restrictive. In this case, we generalise them to allow for a larger set +of possible run-time values, and schedule the block where they appear +for reflowing. The more general type can generalise the types of the +results of the variables in the block, which in turn can generalise the +types that flow into the following blocks, and so on. This process +continues until a fixed point is reached. + +We can consider that all variables are initially assigned the "bottom" +type corresponding to the empty set of possible run-time values. Types +can only ever be generalised, and the model is simple enough to show +that there is no infinite chain of generalisation, so that this process +necessarily terminates. + + +RPython types +------------- + +As seen in `section 3`_, we use the annotator with more than one type +systems. The more interesting and complex one is the RPython type +system, which describes how the input RPython program can be annotated. +The other type systems contain lower-level, C-like types that are mostly +unordered, thus forming more trivial lattices than the one formed by +RPython types. + +The set *A* of RPython types is defined as the following formal terms: + +* Bot, Top -- the minimum and maximum elements (corresponding to + "impossible value" and "most general value"); + +* Int, NonNegInt, Bool -- integers, known-non-negative integers, booleans; + +* Str, Char -- strings, characters (which are strings of length 1); + +* Inst(*class*) -- instance of *class* or a subclass thereof (there is + one such term per *class*); + +* List(*v*) -- list; *v* is a variable summarising the items of the list + (there is one such term per variable); + +* Pbc(*set*) -- where the *set* is a subset of the (finite) set of all + prebuilt constant objects. This set includes all the callables of the + input program: functions, classes, and methods. + +* None -- stands for the singleton ``None`` object of Python. + +* NullableStr, NullableInst(*class*) - a string or ``None``; resp. an + instance or ``None``. + +Figures 6 and 7 shows how these types are ordered to form a lattice. We +mostly use its structure of `join-semilattice`_ only. + +.. graphviz:: image/lattice1.dot + +:Figure 6: the lattice of annotations. + +.. graphviz:: image/lattice2.dot + +:Figure 7: The part about instances and nullable instances, assuming a + simple class hierarchy with only two direct subclasses of + ``object``. + +All list terms for all variables are unordered. The Pbcs form a +classical finite set-of-subsets lattice. In addition, we have left out +a number of other annotations that are irrelevant for the basic +description of the annotator and straightforward to handle: +``Dictionary``, ``Tuple``, ``Float``, ``UnicodePoint``, ``Iterator``, +etc. The complete list is described in `[T]`_. + +The type system moreover comes with a family of rules, which for every +operation and every sensible combination of input types describes the +type of its result variable. Let *V* be the set of Variables that +appear in the user program's flow graphs. Let *b* be a map from *V* to +*A*; it is a "binding" that gives to each variable a type. The purpose +of the annotator is to compute such a binding stepwise. + +Let *x*, *y* and *z* be Variables. We introduce the rule:: + + z=add(x,y), b(x)=Int, b(y)=Int + ------------------------------------------------------ + b' = b with (z->Int) + +which specify that if we see the addition operation applied to Variables +whose current binding is ``Int``, a new binding *b'* can be produced: +it is *b* except on *z*, where we have ``b'(z) = Int``. + +The type inference engine can be seen as applying this kind of rules +repeatedly. It does not apply them in random order, but follows a +forward-propagation order typical of abstract interpretation. + +It is outside the scope of the present paper to describe the type +inference engine and the rules more formally. The difficult points +involve mutable containers - e.g. initially empty list that are filled +somewhere else - and the discovery of instance attributes - in Python, +classes do not declare upfront a fixed set of attributes for their +instances, let alone their types. Both these examples require +sophisticated reflowing techniques that invalidate existing types in +already-annotated basic blocks, to account for the influence of more +general types coming indirectly from a possibly distant part of the +program. The reader is referred to `[D]`_ for more information. + + +Termination and complexity +-------------------------- + +The lattice model clearly contains no infinite chain. Moreover, it is +designed to convince oneself that the number of reflowings required in +practice is small. For example, we are not trying to do range analysis +beyond detecting non-negatives - the reason is that range analysis is +not an essential part of writing *reasonably* efficient code. Consider +that a translated RPython program runs hundreds of times faster than +when the same program is executed by the standard Python interpreter: in +this context, range analysis appears less critical. It is a possible +optimization that we can introduce in a later, optional analysis and +transformation step. + +The worst case behaviors that can appear in the model described above +involve the lattice of Pbcs, involving variables that could contain e.g. +one function object among many. An example of such behavior is code +manipulating a table of function objects: when an item is read out of +the table, its type is a large Pbc set: ``Pbc({f1, f2, f3, ...})``. But +in this example, the whole set is available at once, and not built +incrementally by successive discoveries. This seems to be often the +case in practice: it is not very common for programs to manipulate +objects that belong to a large but finite family - and when they do, the +whole family tends to be available early on, requiring few reflowing. + +This means that *in practice* the complete process requires a time that +is far lower than the worst case. We have experimentally confirmed +this: annotating the whole PyPy interpreter (90'000 lines) takes on the +order of 5 to 10 minutes, and basic blocks are typically only reflown a +handful of times, providing a close-to-linear practical complexity. + +We give formal termination and correctness proofs in `[D]`_, as well as +worst-case bounds and some experimental evidence of their practical +irrelevance. + + +Precision +--------- + +Of course, this would be pointless if the annotation did not give +precise enough information for our needs. We must describe a detail of +the abstract interpretation engine that is critical for precision: the +propagation of conditional types. Consider the following source code +fragment:: + + if isinstance(x, MyClass): + f(x) + else: + g(x) + +Although the type of ``x`` may be some parent class of ``MyClass``, it +can be deduced to be of the more precise type ``Inst(MyClass)`` within +the positive branch of the ``if``. (Remember that our graphs are in SSI +form, which means that the ``x`` inside each basic block is a different +Variable with a possibly different type as annotation.) + +This is implemented by introducing an extended family of types for +boolean values:: + + Bool(v_1: (t_1, f_1), v_2: (t_2, f_2), ...) + +where the *v_n* are variables and *t_n* and *f_n* are types. The result +of a check, like ``isintance()`` above, is typically annotated with such +an extended ``Bool``. The meaning of the type is as follows: if the +run-time value of the boolean is True, then we know that each variable +*v_n* has a type at most as general as *t_n*; and if the boolean is +False, then each variable *v_n* has a type at most as general as *f_n*. +This information is propagated from the check operation to the exit of +the block via such an extended ``Bool`` type, and the conditional exit +logic in the type inference engine uses it to trim the types it +propagates into the next blocks (this is where the *meet* of the lattice +is used). + +With the help of the above technique, we achieve a reasonable precision +in small examples. For larger examples, a different, non-local +technique is required: the specialization of functions. + +As described in the introduction, the most important downside of our +approach is that automatic specialization is a potential +performance-killer. We *do* support specialization, however: we can +generate several independently-annotated copies of the flow graphs of +certain functions. When annotating RPython programs, such +specialization does not happen automatically: we rely on hints provided +by the programmer in the source code, in the form of flags attached to +function objects. As we had this trade-off in mind when we wrote the +Python interpreter of PyPy, we only had to add a dozen or so hints in +the end. + +This does not mean that automatic specialization policies are difficult +to implement. Indeed, the simpler lower-level type systems rely quite +heavily on them: this is because the system code helpers are often +generic and can receive arguments of various C-level types. In this +case, because the types at this level are limited and mostly unordered, +specializing all functions on their input argument's types works well. + +At the level of RPython, on the other hand, the range of specializations +that make sense is much wider. We have used anything between +specialization by the type of an argument, to specialization by an +expected-to-be-constant argument value, to memoized functions that the +type inference engine will actually call during annotation and replace +by look-up tables, to complete overriding of the annotator's behavior in +extreme cases. In this sense, the need for manual specialization turned +into an advantage, in term of simplicity and flexibility of implementing +and using new specialization schemes. + +This conclusion can be generalized. We experimented with a simple +approach to type inference that works well in practice, and that can +very flexibly accomodate changes in the type system and even completely +different type systems. We think that the reasons for this success are +to be found on the one hand in the (reasonable) restrictions we put on +ourselves when designing the RPython language and writing the Python +interpreter of PyPy in RPython, and on the other hand in an ad-hoc type +system that is designed to produce enough precision (but not more) for +the purpose of the subsequent transformations to C-level code. + +We should mention that restricting oneself to write RPython code instead +of Python is still a burden, and that we are not proposing in any way +that the Python language itself should evolve in this direction, nor +even that RPython usage should become widespread. It is a tool designed +with a specific goal in mind, which is the ability to produce reasonably +efficient, stand-alone code in a large variety of environment. @@ -611,6 +888,9 @@ .. _`[T]`: http://codespeak.net/pypy/dist/pypy/doc/translation.html .. _`abstract interpretation`: http://en.wikipedia.org/wiki/Abstract_interpretation .. _Graphviz: http://www.graphviz.org/ +.. _`Hindley-Milner`: http://en.wikipedia.org/wiki/Hindley-Milner_type_inference +.. _`join-semilattice`: http://en.wikipedia.org/wiki/Semilattice +.. _SSA: http://en.wikipedia.org/wiki/Static_single_assignment_form .. http://www.cs.jhu.edu/~scott/pll/constraints.html page to the reference /recent result for constraint-based type inference From tismer at codespeak.net Mon May 29 15:22:46 2006 From: tismer at codespeak.net (tismer at codespeak.net) Date: Mon, 29 May 2006 15:22:46 +0200 (CEST) Subject: [pypy-svn] r27848 - pypy/dist/pypy/module/stackless/test Message-ID: <20060529132246.5417E10050@code0.codespeak.net> Author: tismer Date: Mon May 29 15:22:45 2006 New Revision: 27848 Modified: pypy/dist/pypy/module/stackless/test/stack4.py Log: today it my "English purist" day. Forgive me :-) Modified: pypy/dist/pypy/module/stackless/test/stack4.py ============================================================================== --- pypy/dist/pypy/module/stackless/test/stack4.py (original) +++ pypy/dist/pypy/module/stackless/test/stack4.py Mon May 29 15:22:45 2006 @@ -11,12 +11,12 @@ v = 1 print 'f sending',v outchan.send(v) - print 'f successfully sended',v + print 'f has successfully sent',v v = 2 print 'f sending',v try: outchan.send(v) - print 'f successfully sended',v + print 'f has successfully sent',v except StopIteration: print 'f got StopIteration' From arigo at codespeak.net Mon May 29 15:26:20 2006 From: arigo at codespeak.net (arigo at codespeak.net) Date: Mon, 29 May 2006 15:26:20 +0200 (CEST) Subject: [pypy-svn] r27849 - pypy/extradoc/talk/dls2006 Message-ID: <20060529132620.BE32310057@code0.codespeak.net> Author: arigo Date: Mon May 29 15:26:19 2006 New Revision: 27849 Modified: pypy/extradoc/talk/dls2006/ (props changed) pypy/extradoc/talk/dls2006/draft.txt Log: Latexification of the variables and formulas of the Annotator section. Modified: pypy/extradoc/talk/dls2006/draft.txt ============================================================================== --- pypy/extradoc/talk/dls2006/draft.txt (original) +++ pypy/extradoc/talk/dls2006/draft.txt Mon May 29 15:26:19 2006 @@ -639,29 +639,37 @@ unordered, thus forming more trivial lattices than the one formed by RPython types. -The set *A* of RPython types is defined as the following formal terms: +The set :latexformula:`$A$` of RPython types is defined as the following +formal terms: -* Bot, Top -- the minimum and maximum elements (corresponding to - "impossible value" and "most general value"); +* :latexformula:`$Bot$`, :latexformula:`$Top$` -- the minimum and + maximum elements (corresponding to "impossible value" and "most + general value"); -* Int, NonNegInt, Bool -- integers, known-non-negative integers, booleans; +* :latexformula:`$Int$`, :latexformula:`$NonNegInt$`, + :latexformula:`$Bool$` -- integers, known-non-negative integers, + booleans; -* Str, Char -- strings, characters (which are strings of length 1); +* :latexformula:`$Str$`, :latexformula:`$Char$` -- strings, characters + (which are strings of length 1); -* Inst(*class*) -- instance of *class* or a subclass thereof (there is - one such term per *class*); +* :latexformula:`$Inst(class)$` -- instance of :latexformula:`$class$` + or a subclass thereof (there is one such term per + :latexformula:`$class$`); -* List(*v*) -- list; *v* is a variable summarising the items of the list - (there is one such term per variable); +* :latexformula:`$List(v)$` -- list; :latexformula:`$v$` is a variable + summarising the items of the list (there is one such term per + variable); -* Pbc(*set*) -- where the *set* is a subset of the (finite) set of all - prebuilt constant objects. This set includes all the callables of the - input program: functions, classes, and methods. +* :latexformula:`$Pbc(set)$` -- where the :latexformula:`$set$` is a + subset of the (finite) set of all prebuilt constant objects. This set + includes all the callables of the input program: functions, classes, + and methods. -* None -- stands for the singleton ``None`` object of Python. +* :latexformula:`$None$` -- stands for the singleton ``None`` object of Python. -* NullableStr, NullableInst(*class*) - a string or ``None``; resp. an - instance or ``None``. +* :latexformula:`$NullableStr$`, :latexformula:`$NullableInst(class)$` - + a string or ``None``; resp. an instance or ``None``. Figures 6 and 7 shows how these types are ordered to form a lattice. We mostly use its structure of `join-semilattice`_ only. @@ -685,20 +693,24 @@ The type system moreover comes with a family of rules, which for every operation and every sensible combination of input types describes the -type of its result variable. Let *V* be the set of Variables that -appear in the user program's flow graphs. Let *b* be a map from *V* to -*A*; it is a "binding" that gives to each variable a type. The purpose -of the annotator is to compute such a binding stepwise. - -Let *x*, *y* and *z* be Variables. We introduce the rule:: - - z=add(x,y), b(x)=Int, b(y)=Int - ------------------------------------------------------ - b' = b with (z->Int) +type of its result variable. Let :latexformula:`$V$` be the set of +Variables that appear in the user program's flow graphs. Let +:latexformula:`$b$` be a map from :latexformula:`$V$` to +:latexformula:`$A$`; it is a "binding" that gives to each variable a +type. The purpose of the annotator is to compute such a binding +stepwise. + +Let :latexformula:`$x$`, :latexformula:`$y$` and :latexformula:`$z$` be +Variables. We introduce the rule: + + :latexformula:`$$\begin{array}{c} z = \mathrm{add}(x, y), \; b(x) = + Int, \; Bool \leq b(y) \leq Int \\ \hline b' = b \hbox{\ with\ } (z + \rightarrow Int) \end{array}$$` which specify that if we see the addition operation applied to Variables -whose current binding is ``Int``, a new binding *b'* can be produced: -it is *b* except on *z*, where we have ``b'(z) = Int``. +whose current binding is :latexformula:`$Int$`, a new binding +:latexformula:`$b'$` can be produced: it is :latexformula:`$b$` except +on :latexformula:`$z$`, where we have :latexformula:`$b'(z) = Int$`. The type inference engine can be seen as applying this kind of rules repeatedly. It does not apply them in random order, but follows a @@ -734,12 +746,13 @@ involve the lattice of Pbcs, involving variables that could contain e.g. one function object among many. An example of such behavior is code manipulating a table of function objects: when an item is read out of -the table, its type is a large Pbc set: ``Pbc({f1, f2, f3, ...})``. But -in this example, the whole set is available at once, and not built -incrementally by successive discoveries. This seems to be often the -case in practice: it is not very common for programs to manipulate -objects that belong to a large but finite family - and when they do, the -whole family tends to be available early on, requiring few reflowing. +the table, its type is a large Pbc set: :latexformula:`$Pbc(\{f1, f2, +f3, \ldots\})$`. But in this example, the whole set is available at +once, and not built incrementally by successive discoveries. This seems +to be often the case in practice: it is not very common for programs to +manipulate objects that belong to a large but finite family - and when +they do, the whole family tends to be available early on, requiring few +reflowing. This means that *in practice* the complete process requires a time that is far lower than the worst case. We have experimentally confirmed @@ -773,21 +786,23 @@ Variable with a possibly different type as annotation.) This is implemented by introducing an extended family of types for -boolean values:: +boolean values: - Bool(v_1: (t_1, f_1), v_2: (t_2, f_2), ...) + :latexformula:`$$Bool(v_1: (t_1, f_1), v_2: (t_2, f_2), ...)$$` -where the *v_n* are variables and *t_n* and *f_n* are types. The result -of a check, like ``isintance()`` above, is typically annotated with such -an extended ``Bool``. The meaning of the type is as follows: if the -run-time value of the boolean is True, then we know that each variable -*v_n* has a type at most as general as *t_n*; and if the boolean is -False, then each variable *v_n* has a type at most as general as *f_n*. -This information is propagated from the check operation to the exit of -the block via such an extended ``Bool`` type, and the conditional exit -logic in the type inference engine uses it to trim the types it -propagates into the next blocks (this is where the *meet* of the lattice -is used). +where the :latexformula:`$v_n$` are variables and :latexformula:`$t_n$` +and :latexformula:`$f_n$` are types. The result of a check, like +``isintance()`` above, is typically annotated with such an extended +``Bool``. The meaning of the type is as follows: if the run-time value +of the boolean is True, then we know that each variable +:latexformula:`$v_n$` has a type at most as general as +:latexformula:`$t_n$`; and if the boolean is False, then each variable +:latexformula:`$v_n$` has a type at most as general as +:latexformula:`$f_n$`. This information is propagated from the check +operation to the exit of the block via such an extended ``Bool`` type, +and the conditional exit logic in the type inference engine uses it to +trim the types it propagates into the next blocks (this is where the +*meet* of the lattice is used). With the help of the above technique, we achieve a reasonable precision in small examples. For larger examples, a different, non-local From arigo at codespeak.net Mon May 29 15:30:14 2006 From: arigo at codespeak.net (arigo at codespeak.net) Date: Mon, 29 May 2006 15:30:14 +0200 (CEST) Subject: [pypy-svn] r27850 - pypy/extradoc/talk/dls2006 Message-ID: <20060529133014.47C0310057@code0.codespeak.net> Author: arigo Date: Mon May 29 15:30:13 2006 New Revision: 27850 Modified: pypy/extradoc/talk/dls2006/draft.txt Log: Some more LaTeXifications. Modified: pypy/extradoc/talk/dls2006/draft.txt ============================================================================== --- pypy/extradoc/talk/dls2006/draft.txt (original) +++ pypy/extradoc/talk/dls2006/draft.txt Mon May 29 15:30:13 2006 @@ -563,8 +563,8 @@ `[D]`_ for more information. -Type inference --------------- +The Annotator +------------- The type inference engine, which we call the *annotator*, is the central component of the front-end part of the translation process. Given a @@ -688,8 +688,10 @@ classical finite set-of-subsets lattice. In addition, we have left out a number of other annotations that are irrelevant for the basic description of the annotator and straightforward to handle: -``Dictionary``, ``Tuple``, ``Float``, ``UnicodePoint``, ``Iterator``, -etc. The complete list is described in `[T]`_. +:latexformula:`$Dictionary$`, :latexformula:`$Tuple$`, +:latexformula:`$Float$`, :latexformula:`$UnicodePoint$`, +:latexformula:`$Iterator$`, etc. The complete list is described in +`[T]`_. The type system moreover comes with a family of rules, which for every operation and every sensible combination of input types describes the @@ -780,10 +782,11 @@ g(x) Although the type of ``x`` may be some parent class of ``MyClass``, it -can be deduced to be of the more precise type ``Inst(MyClass)`` within -the positive branch of the ``if``. (Remember that our graphs are in SSI -form, which means that the ``x`` inside each basic block is a different -Variable with a possibly different type as annotation.) +can be deduced to be of the more precise type +:latexformula:`$Inst(MyClass)$` within the positive branch of the +``if``. (Remember that our graphs are in SSI form, which means that the +``x`` inside each basic block is a different Variable with a possibly +different type as annotation.) This is implemented by introducing an extended family of types for boolean values: @@ -793,16 +796,16 @@ where the :latexformula:`$v_n$` are variables and :latexformula:`$t_n$` and :latexformula:`$f_n$` are types. The result of a check, like ``isintance()`` above, is typically annotated with such an extended -``Bool``. The meaning of the type is as follows: if the run-time value -of the boolean is True, then we know that each variable +:latexformula:`$Bool$`. The meaning of the type is as follows: if the +run-time value of the boolean is True, then we know that each variable :latexformula:`$v_n$` has a type at most as general as :latexformula:`$t_n$`; and if the boolean is False, then each variable :latexformula:`$v_n$` has a type at most as general as :latexformula:`$f_n$`. This information is propagated from the check -operation to the exit of the block via such an extended ``Bool`` type, -and the conditional exit logic in the type inference engine uses it to -trim the types it propagates into the next blocks (this is where the -*meet* of the lattice is used). +operation to the exit of the block via such an extended +:latexformula:`$Bool$` type, and the conditional exit logic in the type +inference engine uses it to trim the types it propagates into the next +blocks (this is where the *meet* of the lattice is used). With the help of the above technique, we achieve a reasonable precision in small examples. For larger examples, a different, non-local From tismer at codespeak.net Mon May 29 16:05:27 2006 From: tismer at codespeak.net (tismer at codespeak.net) Date: Mon, 29 May 2006 16:05:27 +0200 (CEST) Subject: [pypy-svn] r27856 - pypy/extradoc/sprintinfo/ddorf2006 Message-ID: <20060529140527.71BDE10053@code0.codespeak.net> Author: tismer Date: Mon May 29 16:05:26 2006 New Revision: 27856 Modified: pypy/extradoc/sprintinfo/ddorf2006/people.txt Log: staying at the "Hotel an der Uni" Modified: pypy/extradoc/sprintinfo/ddorf2006/people.txt ============================================================================== --- pypy/extradoc/sprintinfo/ddorf2006/people.txt (original) +++ pypy/extradoc/sprintinfo/ddorf2006/people.txt Mon May 29 16:05:26 2006 @@ -16,7 +16,7 @@ Maciej Fijalkowski 3rd-9th cfbolz Anders Chrigstroem 1st - 9th Hotel an der Uni Samuele Pedroni 1st - 9th Hotel an der Uni -Christian Tismer 1st - 9th ? +Christian Tismer 1st - 9th Hotel an der Uni Antonio Cuni 1st - 9th cfbolz Anders Lehmann 2nd - 9th Hotel an der Uni ==================== ============== ===================== From nik at codespeak.net Mon May 29 17:52:57 2006 From: nik at codespeak.net (nik at codespeak.net) Date: Mon, 29 May 2006 17:52:57 +0200 (CEST) Subject: [pypy-svn] r27862 - pypy/extradoc/sprintinfo/ddorf2006 Message-ID: <20060529155257.4079C10057@code0.codespeak.net> Author: nik Date: Mon May 29 17:52:56 2006 New Revision: 27862 Modified: pypy/extradoc/sprintinfo/ddorf2006/people.txt Log: my dates. accomodation not quite fixed yet, but i'll sleep anywhere i can lay down my camping mattress. ;) Modified: pypy/extradoc/sprintinfo/ddorf2006/people.txt ============================================================================== --- pypy/extradoc/sprintinfo/ddorf2006/people.txt (original) +++ pypy/extradoc/sprintinfo/ddorf2006/people.txt Mon May 29 17:52:56 2006 @@ -19,6 +19,7 @@ Christian Tismer 1st - 9th Hotel an der Uni Antonio Cuni 1st - 9th cfbolz Anders Lehmann 2nd - 9th Hotel an der Uni +Niklaus Haldimann 2nd - 4th cfbolz (?) ==================== ============== ===================== People on the following list were present at previous sprints: @@ -28,7 +29,6 @@ ==================== ============== ===================== Christian Tismer ? ? Jacob Hallen ? ? -Niklaus Haldimann ? ? Aurelien Campeas ? ? Alexandre Fayolle ? ? Lene Wagner ? ? From ericvrp at codespeak.net Mon May 29 18:19:48 2006 From: ericvrp at codespeak.net (ericvrp at codespeak.net) Date: Mon, 29 May 2006 18:19:48 +0200 (CEST) Subject: [pypy-svn] r27864 - in pypy/dist/pypy: interpreter module/_pickle_support Message-ID: <20060529161948.7725B10041@code0.codespeak.net> Author: ericvrp Date: Mon May 29 18:19:47 2006 New Revision: 27864 Modified: pypy/dist/pypy/interpreter/typedef.py pypy/dist/pypy/module/_pickle_support/__init__.py Log: outcomment that (work in progress) frame pickling. It breaks translation. Modified: pypy/dist/pypy/interpreter/typedef.py ============================================================================== --- pypy/dist/pypy/interpreter/typedef.py (original) +++ pypy/dist/pypy/interpreter/typedef.py Mon May 29 18:19:47 2006 @@ -521,8 +521,8 @@ ) PyFrame.typedef = TypeDef('frame', - __reduce__ = interp2app(PyFrame.descr__reduce__, - unwrap_spec=['self', ObjSpace]), + #__reduce__ = interp2app(PyFrame.descr__reduce__, + # unwrap_spec=['self', ObjSpace]), f_builtins = GetSetProperty(PyFrame.fget_f_builtins), f_lineno = GetSetProperty(PyFrame.fget_f_lineno, PyFrame.fset_f_lineno), f_back = GetSetProperty(PyFrame.fget_f_back), Modified: pypy/dist/pypy/module/_pickle_support/__init__.py ============================================================================== --- pypy/dist/pypy/module/_pickle_support/__init__.py (original) +++ pypy/dist/pypy/module/_pickle_support/__init__.py Mon May 29 18:19:47 2006 @@ -15,5 +15,5 @@ 'dictiter_surrogate_new' : 'maker.dictiter_surrogate_new', 'seqiter_new' : 'maker.seqiter_new', 'reverseseqiter_new' : 'maker.reverseseqiter_new', - 'frame_new' : 'maker.frame_new', + #'frame_new' : 'maker.frame_new', } From hpk at codespeak.net Mon May 29 18:43:17 2006 From: hpk at codespeak.net (hpk at codespeak.net) Date: Mon, 29 May 2006 18:43:17 +0200 (CEST) Subject: [pypy-svn] r27868 - pypy/extradoc/minute Message-ID: <20060529164317.4A3A710069@code0.codespeak.net> Author: hpk Date: Mon May 29 18:43:06 2006 New Revision: 27868 Added: pypy/extradoc/minute/pypy-sync-2006-05-29.txt Log: draft minutes for today's pypy-sync Added: pypy/extradoc/minute/pypy-sync-2006-05-29.txt ============================================================================== --- (empty file) +++ pypy/extradoc/minute/pypy-sync-2006-05-29.txt Mon May 29 18:43:06 2006 @@ -0,0 +1,274 @@ +#pypy-sync 29th May 2006, 5pm (UTC+2) +===================================================== + +attendants: michael (mod and minutes), anto (beforehand), samuele, + carl, eric, arre, armin, anders, holger, nik + +: everybody posted, see log below. + +activity reports +----------------- + +everybody posted, see log below. + +Duesseldorf sprint planning +------------------------------ + +- thursday evening: a beer meeting point is 8pm "hotel an der uni" +- friday morning: meeting point and time will be posted by Armin + holger will also try to get information. +- monday is likely the breakday +- armin may only arrive on the 4th + +- release day is set as the 7th, Wednesday + +DLS paper +---------------- + +The work on this is well in progress, says Armin. But he +needs two days of work with Samuele on some specific sections. +Michael offers to review wednesday afternoon. + +Also, some LateX fighting is foreseen, help would +be appreciated! + +EP pre and post sprint +------------------------------- + +We decided to go for the full 6th-9th (both including) as the +post-EP sprint time. Sprint is scheduled in Geneva. +Announcement pending. + +pre-EP sprint: it is not clear yet who could come and focus on +the core sprint. Carl, Michael and possibly Holger will not +be able to attend. Niklaus, Christian, Armin, Anders and Arre +could attend. + +We'll decide in DDorf about the pre-EP sprint +and its location (Geneva or Leysin). + +Misc topics +------------- + +Michael and holger will care tomorrow for co-ordinating/doing +the pypy talk EuroPython 2006 submissions. + +Christian reported that Gerald stopped working for tismerysoft +from March on and that Eric will stop on 1st July. + +IRC logs +------------- + +:: + + May 29 16:50:43 --> You are now talking on #pypy-sync + May 29 16:50:43 --- Topic for #pypy-sync is PyPy - the flexible snake. This channel is used for pair programming and sync meetings. + May 29 16:50:43 --- Topic for #pypy-sync set by xorAxAx at Sun Apr 16 21:44:23 + May 29 17:01:09 10:01 + May 29 17:01:14 hum, a few people missing still that's we'd like to have here + May 29 17:01:15 17:01 + May 29 17:01:15 hi christian + May 29 17:01:21 hi Holgi + May 29 17:02:08 Hi! + May 29 17:02:12 hi + May 29 17:02:16 mwh: are you here? + May 29 17:02:21 no need to wait for Eric or Samuele, btw + May 29 17:02:33 ah right, i am here + May 29 17:02:33 --> nikh (n=nikh at 11.234.62.81.cust.bluewin.ch) has joined #pypy-sync + May 29 17:03:39 yip, i had hoped that armin comes + May 29 17:04:00 Stephan seems to be busy in the afternoon + May 29 17:04:10 anyway, let's start, here is the topic list: + May 29 17:04:24 * activity reports + May 29 17:04:24 * duesseldorf sprint planning + May 29 17:04:24 * DLS paper status + May 29 17:04:24 * pre-EP sprint + May 29 17:04:44 ok, I'll start pasting + May 29 17:04:51 go ahead + May 29 17:04:55 DONE: Need For Speed sprint: worked on an RPython version of decimal.py (not finished due to problems with the way it is written and prebuilt classes) + May 29 17:05:04 NEXT: supporting Stackless and pickling work, still seaching for "the" way to handle threads, need to sync with Samuele + May 29 17:05:10 BLOCK: hop.inputconst(Ptr(PyObject), nullptr(PyObject)) + May 29 17:05:21 LAST: sprint issues, june technical project assessment, SoC issues + May 29 17:05:21 NEXT: DDorf sprint, HHU admin meeting, 0.9 works + May 29 17:05:21 BLOCKERS: too much + May 29 17:05:29 LAST: university stuff + May 29 17:05:29 NEXT: university stuff, a bit of sprinting + May 29 17:05:29 BLOCKERS: none + May 29 17:05:31 --- You are now known as ericvrp + May 29 17:05:35 PREV: OWLreasoner + May 29 17:05:35 PREV: OWLreasoner + May 29 17:05:35 NEXT: more OWLreasoner and sprint + May 29 17:05:35 blocker: - + May 29 17:05:37 LAST: pickling + put profile based optimization in benchmark cronjob + May 29 17:05:37 + speedup pypy-llvm + May 29 17:05:37 NEXT: pickling + May 29 17:05:37 BLOCKERS: - + May 29 17:05:40 --- You are now known as hpk + May 29 17:05:43 PREV: Vacation + May 29 17:05:44 NEXT: Some Unicode work, Duesseldorf + May 29 17:05:44 BLOCKERS: - + May 29 17:06:18 LAST: this and that, some gc stuff + May 29 17:06:19 NEXT: dls paper, travel, sprint + May 29 17:06:19 BLOCKERS: keeping up + May 29 17:06:40 ok then on to DDorf sprint planning + May 29 17:06:55 stakkars: i guess it makes most sense to try to remove your blocker on #pypy later + May 29 17:07:13 DDorf: most of us already arrive on 1st + May 29 17:07:20 do we have a meeting point/time somewhere? + May 29 17:07:23 if you know what it means then you know that it is None :-) + May 29 17:08:14 i arrive pretty late on the 1st + May 29 17:08:22 ah ok + May 29 17:08:22 i don't actually know where we are sprinting + May 29 17:08:23 I will first arrive at 23 + May 29 17:08:46 I have no clue when I arrive. Will take some train + May 29 17:08:50 i guess we could meet somewhere near armin's and my office + May 29 17:08:56 stakkars: which day, at least? + May 29 17:09:02 or at the "hotel an der uni" where most everybody stays apparently + May 29 17:09:11 as I said in people.txt, June 1st. + May 29 17:09:16 stakkars: ok + May 29 17:09:28 ok, i guess i might drop by the hotel at 8 pm or so, more on the mobile phone + May 29 17:09:42 then we should meet there + May 29 17:09:50 --> arigo (n=arigo at c-1f8b70d5.022-54-67626719.cust.bredbandsbolaget.se) has joined #pypy-sync + May 29 17:09:55 arigo: hi armin! + May 29 17:10:02 welcome! + May 29 17:10:05 sorry + May 29 17:10:19 we just said that some of us weill meet already on june 1st 8pm "hotel an der uni" + May 29 17:10:33 another question was: where do we meet friday morning + May 29 17:10:49 at the CS department, I expect + May 29 17:10:59 it would be good if someone local could post some precise enough information + May 29 17:11:11 indeed + May 29 17:11:12 like street name and number or so + May 29 17:11:15 prepare to get lost :) + May 29 17:11:20 yes :-) + May 29 17:11:20 the hhu campus is a maze + May 29 17:11:37 great, i'll be there on 1st already to meet with lene and HHU admins at 2pm, btw + May 29 17:12:35 do we go for a breakday on monday? + May 29 17:13:10 well, if DDorf has something worthy to break for :-) + May 29 17:13:17 and a 0.9 release on wednesday? + May 29 17:13:39 i'd not like to do it on the last day (which seems to become the 8th/thursday where everybody is still there) + May 29 17:13:48 hpk: makes sense + May 29 17:13:51 just to mention it, I'm still unsure if I arrive the 1st or only the 4th + May 29 17:14:03 Monday is a public holiday ? + May 29 17:14:14 aleale: in germany yes, don't know about others + May 29 17:14:15 (i'm trying to find a map on the hhu website, i know one is there somewhere...) + May 29 17:14:37 arigo: when will you be sure? + May 29 17:14:49 i have sufficient keys to get in at any time + May 29 17:15:01 arigo: good to know, then 5th as a breakday would not be so great + May 29 17:15:20 hpk: I thought about it, and no other day looks very great anyway, so never mind + May 29 17:15:46 ok, it's going to be a busy sprint, i think + May 29 17:15:55 also, Carl is not around? he's the only one that knows about the sprint venue AFAIK + May 29 17:16:05 arigo: i'll ask him when i see him + May 29 17:16:23 arigo: i guess michael would know if we get desparate + May 29 17:16:26 he is very likely out a few days due to personal issues, unfortunately + May 29 17:16:58 ok, then I'll post information about reaching the CS department, at least + May 29 17:17:17 arigo: ok, i'll also mail leuschel in a second (need to confirm the 1st june date anyway) + May 29 17:17:27 he probably has a good pointer + May 29 17:17:39 i'll CC you so you can repost/enrich and send to pypy-sprint + May 29 17:17:42 i expect so + May 29 17:17:47 and hopefully no weak ref + May 29 17:17:51 next topic: DLS paper + May 29 17:18:01 what is the status? + May 29 17:18:23 (DLS = dynamic language symposium, deadline 30 or 31st may) + May 29 17:18:25 it seems to be about 50% done? + May 29 17:18:31 deadline is june 1 + May 29 17:18:35 including? + May 29 17:18:40 I think the meat of the text is done + May 29 17:18:46 http://www.dcl.hpi.uni-potsdam.de/dls2006/openconf.php + May 29 17:19:02 hpk: don't know, but as everyone is traveling on the 1st... + May 29 17:19:14 except armin maybe :) + May 29 17:19:22 31st becomes the actual deadline indeed + May 29 17:19:43 makes some sense + May 29 17:19:46 this wednesday, uff + May 29 17:20:03 i will try to read through the paper tomorrow + May 29 17:20:19 then we can spend wednesday fighting with latex :/ + May 29 17:20:20 I definitely plan to work on it with Samuele for the whole next two days + May 29 17:20:25 oh right + May 29 17:20:40 hum, that includes the fighting with latex day, hopefully + May 29 17:21:15 * stakkars needs to add a tiny topic to the very, just telling about personnell changes in tismerysoft + May 29 17:21:22 very end + May 29 17:21:43 so the DLS paper status is "in progress" + May 29 17:21:54 arigo: ok, please scream if you need help for reviewing or even writing + May 29 17:21:54 actively so, yes + May 29 17:22:14 the more precise the scream the better :) + May 29 17:22:27 arigo: if it helps, I can make up some time on Wednesday + May 29 17:22:30 what is left are the parts that only Samuele can really do right + May 29 17:22:37 i see + May 29 17:22:44 the references, related work etc. + May 29 17:23:04 arigo: well, thanks a lot for taking up on this, btw + May 29 17:23:47 one thing: i saw that hardly anyone assigned 0.9 issues to himself, it would really be helpful if we could distribute the efforts, also before the sprint + May 29 17:24:27 how about going through the list on Thursday evning, together? + May 29 17:24:46 might make sense, yes, or friday morning, where we need a planning session anyway + May 29 17:24:56 thursday evening not everybody will be there + May 29 17:25:12 but enough to get 80% off the kist + May 29 17:25:15 list + May 29 17:25:21 mwh: how much are EP deadlines interfering with our sprint timing? + May 29 17:25:41 well, the submission deadline for talks is the 31st + May 29 17:25:52 *gulp* + May 29 17:26:05 mwh: sure but i mean the sprint itself + May 29 17:26:10 so it would be nice to get a preliminary timetable up by the 4th or so + May 29 17:26:16 mwh: but we indeed need to submit our talks that we discussed about last time + May 29 17:26:22 we need to get some pypy talk submissions in + May 29 17:26:24 yes, indeed + May 29 17:26:33 before the sprint... + May 29 17:26:45 i put a small summary of the ideas into extradoc + May 29 17:26:56 mwh: shall we co-ordinate tomorrow on #pypy regarding the talk submissions and see how we get them done? + May 29 17:26:58 we need to decide who gives what talk + May 29 17:27:01 hpk: ok + May 29 17:27:10 mwh: yes + May 29 17:27:18 tomorrow then + May 29 17:27:39 ok, last topic + May 29 17:27:43 hpk: can you explain your pre-ep sprint mail then, you seem to have confused armin and me at least :) + May 29 17:27:57 me 2 + May 29 17:28:08 mwh: you answered "you had similar thoughts", didn't you? + May 29 17:28:41 well, yes, but i'm not sure what you were in fact proposing + May 29 17:28:44 let's simply ask: who would come to a four-day pre-EP sprint and promise to 90% focus on pypy core and not on anything EP related? + May 29 17:29:03 i think i want to be in geneva well before the conference + May 29 17:29:13 i don't think i could reasonably sprint in leysin say + May 29 17:29:20 i know that Carl can't either + May 29 17:29:29 this doesn't apply to everyone else so much necessarily! + May 29 17:29:46 and i personally doubt that anyone would have the focus we had last time in leysin (where we convened for almost 7 days, without many distractions!) + May 29 17:29:51 speaking for myself, Leysin would be preferable + May 29 17:30:34 I dont have anything to do concerning EP + May 29 17:30:44 anyway, let's close the official meeting (apart from christian's point) and decide in Duesseldorf about pre-EP + + May 29 17:30:52 for what it's worth, i could come to a pre-EP sprint (but not the post-EP one). i'd prefer geneva. + May 29 17:31:12 * hpk is not out to block it, just trying to realistically make a guess about how effective it would be + May 29 17:31:14 I think to come to whatsoever + May 29 17:31:31 shortly to my point? + May 29 17:31:47 sure + May 29 17:32:17 1. Gerald has resigned from tismerysoft, backward by the end of March. + May 29 17:32:44 2. Eric is leaving the company on his own behalf by end of June. + May 29 17:33:12 3. I'm trying to get Richard back into more PyPy work by motivating EWT. This is in progress. + May 29 17:33:14 EOF + May 29 17:33:24 Pre- and/or post- is not problem for me. + May 29 17:33:43 the post-EP one is not in question + May 29 17:34:23 side note: EWT people are coming to EP, and might consider to join a sprint if they are welcome. + May 29 17:34:30 stakkars: i see, thanks for letting us know + May 29 17:34:49 * stakkars is actually sad about 1/2 but well + May 29 17:35:09 i imagine + May 29 17:36:20 nikh: good to know, that you'd come to pre-ep :) + May 29 17:36:24 any other business? + May 29 17:36:25 can we decide now that the post-EP sprint from 6th to 9th in Geneva will occur? + May 29 17:36:56 sure, it think it's clear that we do a post-ep, question is how long + May 29 17:37:00 the situation seems confused enough that I think we should clarify this now, if possible + May 29 17:37:15 6th-9th are the official dates, I don't think it can easily be longer + May 29 17:37:30 I think so, yes + May 29 17:37:30 arigo: sounds good to me + May 29 17:37:33 ok, then let's go for that + May 29 17:37:46 9th including (to not loose another of those few days) + May 29 17:37:53 yes + May 29 17:38:07 so people should usually stay until 10th, unless they only have a short trip + May 29 17:38:41 makes sense + May 29 17:38:46 ok, this is set, then if nobody objects (/me notes that he is not sure about his full post-EP attendance yet) + May 29 17:39:07 not sure about what? + May 29 17:39:16 not sure about coming the full post-ep time myself + May 29 17:39:16 ah, your attendance + May 29 17:39:19 right + May 29 17:39:43 * hpk redundantly sidenotes that he'd like to get to some project planning regarding the rest of the year, including sprints + May 29 17:39:47 my auto-detypo-filter made me read "this" :-) + May 29 17:40:15 hpk: i guess ddorf is a good place for that + May 29 17:41:15 yip + May 29 17:41:37 (the meeting is closed, in case nobody noticed yet :) + May 29 17:42:01 bye + May 29 17:42:05 ok, bye then ;) + May 29 17:42:11 bye! + May 29 17:42:14 bye + May 29 17:42:17 bye From tismer at codespeak.net Mon May 29 19:25:13 2006 From: tismer at codespeak.net (tismer at codespeak.net) Date: Mon, 29 May 2006 19:25:13 +0200 (CEST) Subject: [pypy-svn] r27870 - pypy/extradoc/minute Message-ID: <20060529172513.3A14810053@code0.codespeak.net> Author: tismer Date: Mon May 29 19:25:12 2006 New Revision: 27870 Modified: pypy/extradoc/minute/pypy-sync-2006-05-29.txt Log: small correction for job at tismerysoft endings Modified: pypy/extradoc/minute/pypy-sync-2006-05-29.txt ============================================================================== --- pypy/extradoc/minute/pypy-sync-2006-05-29.txt (original) +++ pypy/extradoc/minute/pypy-sync-2006-05-29.txt Mon May 29 19:25:12 2006 @@ -54,7 +54,7 @@ the pypy talk EuroPython 2006 submissions. Christian reported that Gerald stopped working for tismerysoft -from March on and that Eric will stop on 1st July. +by end of March on and that Eric will stop by end of June. IRC logs ------------- From tismer at codespeak.net Mon May 29 19:26:01 2006 From: tismer at codespeak.net (tismer at codespeak.net) Date: Mon, 29 May 2006 19:26:01 +0200 (CEST) Subject: [pypy-svn] r27871 - pypy/extradoc/minute Message-ID: <20060529172601.A555A10053@code0.codespeak.net> Author: tismer Date: Mon May 29 19:26:00 2006 New Revision: 27871 Modified: pypy/extradoc/minute/pypy-sync-2006-05-11.txt (props changed) pypy/extradoc/minute/pypy-sync-2006-05-29.txt (props changed) Log: eolstyle:native From fijal at codespeak.net Mon May 29 19:39:42 2006 From: fijal at codespeak.net (fijal at codespeak.net) Date: Mon, 29 May 2006 19:39:42 +0200 (CEST) Subject: [pypy-svn] r27872 - pypy/dist/pypy/translator/cli Message-ID: <20060529173942.BAC2910063@code0.codespeak.net> Author: fijal Date: Mon May 29 19:39:41 2006 New Revision: 27872 Modified: pypy/dist/pypy/translator/cli/database.py pypy/dist/pypy/translator/cli/gencli.py pypy/dist/pypy/translator/cli/ilgenerator.py pypy/dist/pypy/translator/cli/oopspec.py Log: Necessary compatibility issues for gencli reuse by genjs. Modified: pypy/dist/pypy/translator/cli/database.py ============================================================================== --- pypy/dist/pypy/translator/cli/database.py (original) +++ pypy/dist/pypy/translator/cli/database.py Mon May 29 19:39:41 2006 @@ -69,8 +69,6 @@ return '%s.%s::%s' % (CONST_NAMESPACE, CONST_CLASS, name) def gen_constants(self, ilasm): - if not ilasm.show_const(): - return ilasm.begin_namespace(CONST_NAMESPACE) ilasm.begin_class(CONST_CLASS) @@ -104,7 +102,7 @@ # the constructor calls the steps in reverse order ilasm.begin_function('.cctor', [], 'void', False, 'static', - 'specialname', 'rtspecialname', 'default') + 'specialname', 'rtspecialname', 'default') last_step = step-1 for step in xrange(last_step, -1, -1): Modified: pypy/dist/pypy/translator/cli/gencli.py ============================================================================== --- pypy/dist/pypy/translator/cli/gencli.py (original) +++ pypy/dist/pypy/translator/cli/gencli.py Mon May 29 19:39:41 2006 @@ -26,12 +26,12 @@ class GenCli(object): def __init__(self, tmpdir, translator, entrypoint=None, type_system_class=CTS, opcode_dict=opcodes, name_suffix='.il', function_class=Function, - pending_graphs=()): + database_class = LowLevelDatabase, pending_graphs=()): self.tmpdir = tmpdir self.translator = translator self.entrypoint = entrypoint - self.db = LowLevelDatabase( type_system_class = type_system_class , opcode_dict = opcode_dict, - function_class = function_class ) + self.db = database_class(type_system_class = type_system_class, opcode_dict = opcode_dict, + function_class = function_class) for graph in pending_graphs: self.db.pending_function(graph) Modified: pypy/dist/pypy/translator/cli/ilgenerator.py ============================================================================== --- pypy/dist/pypy/translator/cli/ilgenerator.py (original) +++ pypy/dist/pypy/translator/cli/ilgenerator.py Mon May 29 19:39:41 2006 @@ -43,9 +43,6 @@ self.code.writeline('.assembly extern pypylib {}') self.code.writeline('.assembly %s {}' % name) - def show_const(self): - return True - def close(self): self.out.close() Modified: pypy/dist/pypy/translator/cli/oopspec.py ============================================================================== --- pypy/dist/pypy/translator/cli/oopspec.py (original) +++ pypy/dist/pypy/translator/cli/oopspec.py Mon May 29 19:39:41 2006 @@ -10,6 +10,9 @@ # builtin methods take the same arguments of the corresponding # ll_* function. full_name, _ = oopspec.split('(', 1) + + if len(full_name.split('.')) != 2: + return None try: type_name, method_name = full_name.split('.') except ValueError: From fijal at codespeak.net Mon May 29 19:45:55 2006 From: fijal at codespeak.net (fijal at codespeak.net) Date: Mon, 29 May 2006 19:45:55 +0200 (CEST) Subject: [pypy-svn] r27873 - in pypy/dist/pypy/translator/js2: . test Message-ID: <20060529174555.402F810069@code0.codespeak.net> Author: fijal Date: Mon May 29 19:45:52 2006 New Revision: 27873 Added: pypy/dist/pypy/translator/js2/_builtin.py pypy/dist/pypy/translator/js2/_class.py pypy/dist/pypy/translator/js2/database.py pypy/dist/pypy/translator/js2/test/test_class.py pypy/dist/pypy/translator/js2/test/test_exc_operation.py pypy/dist/pypy/translator/js2/test/test_exception.py pypy/dist/pypy/translator/js2/test/test_genllvm.py pypy/dist/pypy/translator/js2/test/test_genllvm1.py pypy/dist/pypy/translator/js2/test/test_jseval.py pypy/dist/pypy/translator/js2/test/test_loops.py pypy/dist/pypy/translator/js2/test/test_seq.py pypy/dist/pypy/translator/js2/test/test_snippet.py pypy/dist/pypy/translator/js2/test/test_typed.py Modified: pypy/dist/pypy/translator/js2/asmgen.py pypy/dist/pypy/translator/js2/function.py pypy/dist/pypy/translator/js2/js.py pypy/dist/pypy/translator/js2/jts.py pypy/dist/pypy/translator/js2/opcodes.py pypy/dist/pypy/translator/js2/support.py pypy/dist/pypy/translator/js2/test/runtest.py Log: - Added some passing test - Added basic class support (without inheritance) - Several bugfixes - Added constant support (list, string, instance, primitive, no dict yet) - Added basic builtin functions and methods mapping (altough I'm not particurarly happy with this solution) - Added some new opcodes, mostly ootypesystem related Added: pypy/dist/pypy/translator/js2/_builtin.py ============================================================================== --- (empty file) +++ pypy/dist/pypy/translator/js2/_builtin.py Mon May 29 19:45:52 2006 @@ -0,0 +1,79 @@ + +""" several builtins mapping +""" + +from pypy.rpython.ootypesystem.ootype import List, Meth, Void, String + +from pypy.translator.js2.log import log + +import re + +SETITEM = 1 + +class _Builtins(object): + BUILTIN_MAP = { + 'js_jseval' : ('eval', False), + 'newlist' : ('[]', True), + 'alloc_and_set' : ('alloc_and_set', False), + 'strconcat' : ('strconcat', False), + 'stritem' : ('stritem', False), + 'delitem_nonneg' : ('delitem', False), + 'streq' : 'equal', + 'strcmp' : ('strcmp', False), + 'startswith' : ('startswith', False), + 'endswith' : ('endswith', False), + } + + BUILTIN_METHOD_MAP = { + List: { + 'll_setitem_fast' : 'list_ll_setitem', + 'll_getitem_fast' : 'list_ll_getitem', + '_ll_resize' : 'list_ll_resize', + '_ll_resize_ge' : 'list_ll_resize', + '_ll_resize_le' : 'list_ll_resize', + 'll_length' : ('length', True), + }, + String.__class__: { + 'll_strlen' : ('length', True), + 'll_stritem_nonneg' : 'list_ll_getitem', + } + } + + def real_name(self, _name): + name = _name.split('__')[0] + m = re.match("^ll_(.*)$", name) + if not m: + return None + return m.group(1) + + def map_builtin_function(self, const, inst, args, generator): + name = self.real_name(const.value._name) + if name is None: + return None + + if getattr(const.value, 'suggested_primitive', False): + log("Suggested primitive %r"%const) + try: + model = self.BUILTIN_MAP[name] + if isinstance(model, tuple): + return model + else: + getattr(inst, model)(None, args, generator) + return False + except KeyError: + return None + + def map_builtin_method(self, base_obj, method, args, inst, generator): + try: + log("Baseobj: %r, method: %r"%(base_obj.concretetype, method)) + model = self.BUILTIN_METHOD_MAP[base_obj.concretetype.__class__][method] + if isinstance(model,tuple): + log("Suggested simple mapping %r"%(model,)) + return model + else: + getattr(inst, model)(base_obj, args, generator) + return False + except KeyError: + return None + +Builtins = _Builtins() Added: pypy/dist/pypy/translator/js2/_class.py ============================================================================== --- (empty file) +++ pypy/dist/pypy/translator/js2/_class.py Mon May 29 19:45:52 2006 @@ -0,0 +1,71 @@ + +""" genjs class definition +""" + +from pypy.translator.cli.node import Node +from pypy.translator.cli.cts import CTS + +class Class(Node): + def __init__(self, db, classdef): + self.db = db + self.cts = db.type_system_class(db) + self.classdef = classdef + self.name = classdef._name.split('.')[-1] + + if not self.is_root(classdef): + self.db.pending_class(classdef._superclass) + + def __hash__(self): + return hash(self.classdef) + + def __eq__(self, other): + return self.classdef == other.classdef + + def is_root(classdef): + return classdef._superclass is None + is_root = staticmethod(is_root) + + def get_name(self): + return self.name + + def get_base_class(self): + base_class = self.classdef._superclass + if self.is_root(base_class): + return '[mscorlib]System.Object' + else: + return base_class._name + + def render(self, ilasm): + if self.is_root(self.classdef): + return + + if self.db.class_name(self.classdef) is not None: + return # already rendered + + self.ilasm = ilasm + + ilasm.begin_function(self.name, []) + ilasm.end_function() + + #for f_name, (f_type, f_default) in self.classdef._fields.iteritems(): + # cts_type = self.cts.lltype_to_cts(f_type) + #if cts_type != 'void': + # ilasm.field(f_name, cts_type) + + # TODO: should the .ctor set the default values? + #self._ctor() + + # lazy import to avoid circular dependencies + #import pypy.translator.cli.function as function + for m_name, m_meth in self.classdef._methods.iteritems(): + f = self.db.function_class(self.db, m_meth.graph, m_name, is_method = True, _class = self.name) + f.render(ilasm) + + self.db.record_class(self.classdef, self.name) + + #def _ctor(self): + # self.ilasm.begin_function('.ctor', [], 'void', False, 'specialname', 'rtspecialname', 'instance') + # self.ilasm.opcode('ldarg.0') + # self.ilasm.call('instance void %s::.ctor()' % self.get_base_class()) + # self.ilasm.opcode('ret') + # self.ilasm.end_function() Modified: pypy/dist/pypy/translator/js2/asmgen.py ============================================================================== --- pypy/dist/pypy/translator/js2/asmgen.py (original) +++ pypy/dist/pypy/translator/js2/asmgen.py Mon May 29 19:45:52 2006 @@ -4,8 +4,7 @@ from pypy.translator.js2.log import log -from pypy.rpython.lltypesystem.lltype import Signed, Unsigned, Void, Bool, Float -from pypy.rpython.lltypesystem.lltype import SignedLongLong, UnsignedLongLong +from pypy.objspace.flow.model import Variable from StringIO import StringIO @@ -45,6 +44,8 @@ self.subst_table = subst_table def pop(self): + if len(self.l) == 0: + return "sth" el = self.l.pop() return self.subst_table.get(el, el) @@ -64,16 +65,19 @@ self.right_hand = Queue([], self.subst_table) self.codegenerator = CodeGenerator(outfile) - def show_const(self): - return False - - def begin_function(self, name, arglist, returntype, is_entrypoint = False, *args): + def begin_function(self, name, arglist): args = ",".join([i[1] for i in arglist]) self.codegenerator.write("function %s (%s) "%(name, args)) self.codegenerator.openblock() + def begin_method(self, name, _class, arglist): + args = ",".join([i[1] for i in arglist]) + self.codegenerator.write("%s.prototype.%s = function (%s)"%(_class, name, args)) + self.codegenerator.openblock() + def end_function(self): self.codegenerator.closeblock() + self.codegenerator.writeline("") def locals(self, loc): self.codegenerator.writeline("var "+",".join([i[1] for i in loc])+";") @@ -90,31 +94,12 @@ def load_local(self, v): self.right_hand.append(v.name) - def load_const(self, _type, v): - if _type is Bool: - if v == False: - val = 'false' - else: - val = 'true' - else: - val = str(v) - self.right_hand.append(val) - + def load_const(self, v): + self.right_hand.append(v) + def ret(self): self.codegenerator.writeline("return ( %s );"%self.right_hand.pop()) - def begin_namespace(self,namespace): - pass - - def end_namespace(self): - pass - - def begin_class(self,cl): - raise NotImplementedError("Class support") - - def end_class(self): - raise NotImplementedError("Class support") - def emit(self, opcode, *args): v1 = self.right_hand.pop() v2 = self.right_hand.pop() @@ -122,8 +107,10 @@ def call(self, func): func_name, args = func - real_args = ",".join([self.right_hand.pop() for i in xrange(len(args))] ) - self.right_hand.append("%s ( %s )"%(func_name, real_args)) + l = [self.right_hand.pop() for i in xrange(len(args))] + l.reverse() + real_args = ",".join(l) + self.right_hand.append("%s ( %s )" % (func_name, real_args)) def branch_if(self, arg, exitcase): arg_name = self.subst_table.get(arg.name, arg.name) @@ -151,11 +138,91 @@ pass def change_name(self, from_name, to_name): - self.subst_table[from_name.name] = to_name.name - #pass + # if isinstance(from_name,Variable) and isinstance(to_name,Variable): + # self.subst_table[from_name.name] = to_name.name + pass + + def cast_function(self, name, num): + # FIXME: redundancy with call + args = [self.right_hand.pop() for i in xrange(num)] + args.reverse() + arg_list = ",".join(args) + self.right_hand.append("%s ( %s )"%(name, arg_list)) + + def prefix_op(self, st): + self.right_hand.append("%s%s"%(st, self.right_hand.pop())) + + #def field(self, f_name, cts_type): + # pass + + def set_static_field(self, _type, namespace, _class, varname): + self.codegenerator.writeline("%s.prototype.%s = %s;"%(_class, varname, self.right_hand.pop())) + + #def load_set_field(self, _type, name): + # #self.right_hand.append("") + # #self.codegenerator.writeline("set field %r %r"%(_type, name)) + # pass + + def set_field(self, useless_parameter, name): + v = self.right_hand.pop() + self.codegenerator.writeline("%s.%s = %s;"%(self.right_hand.pop(), name, v)) + self.right_hand.append(None) + + def call_method(self, obj, name, signature): + l = [self.right_hand.pop() for i in signature] + l.reverse() + args = ",".join(l) + self.right_hand.append("%s.%s(%s)"%(self.right_hand.pop(), name, args)) + + def get_field(self, name): + self.right_hand.append("%s.%s"%(self.right_hand.pop(), name)) + + def new(self, obj): + log("New: %r"%obj) + self.right_hand.append("new %s()"%obj) + + def load_self(self): + self.right_hand.append("this") + + def store_void(self): + v = self.right_hand.pop() + if v is not None: + self.codegenerator.writeline(v+";") + #self.right_hand.pop() + + def begin_consts(self, name): + # load consts, maybe more try to use stack-based features? + self.codegenerator.writeline("%s = {};"%name) + + def new_obj(self): + self.right_hand.append("{}") + + def new_list(self): + self.right_hand.append("[]") + + # FIXME: will refactor later + load_str = load_const + + def list_setitem(self): + item = self.right_hand.pop() + value = self.right_hand.pop() + lst = self.right_hand.pop() + self.right_hand.append("%s[%s]=%s"%(lst, item, value)) + + def list_getitem(self): + item = self.right_hand.pop() + lst = self.right_hand.pop() + self.right_hand.append("%s[%s]"%(lst, item)) - def cast_floor(self): - self.right_hand.append("Math.floor ( %s )"%self.right_hand.pop()) + def load_void(self): + self.right_hand.append("undefined") + + def begin_try(self): + self.codegenerator.write("try ") + self.codegenerator.openblock() + + def end_try(self): + self.codegenerator.closeblock() #def finish ( self ): # self . outfile . write ( "%r" % self . right_hand ) Added: pypy/dist/pypy/translator/js2/database.py ============================================================================== --- (empty file) +++ pypy/dist/pypy/translator/js2/database.py Mon May 29 19:45:52 2006 @@ -0,0 +1,333 @@ + +""" genjs constant database module +""" + +from pypy.rpython.ootypesystem import ootype +from pypy.translator.js2.opcodes import opcodes +from pypy.translator.js2.function import Function +from pypy.translator.js2.log import log +from pypy.translator.js2.jts import JTS +from pypy.translator.js2._class import Class +from pypy.translator.js2.support import JavascriptNameManager + +from pypy.rpython.lltypesystem.lltype import Signed, Unsigned, Void, Bool, Float +from pypy.rpython.lltypesystem.lltype import SignedLongLong, UnsignedLongLong, typeOf +from pypy.rpython.lltypesystem.lltype import Char, UniChar +from pypy.rpython.ootypesystem import ootype + +from pypy.objspace.flow.model import Variable, Constant + +try: + set +except NameError: + from sets import Set as set + +class LowLevelDatabase(object): + def __init__(self, type_system_class = JTS, opcode_dict = opcodes, function_class = Function): + self._pending_nodes = set() + self.opcode_dict = opcode_dict + self._rendered_nodes = set() + self.function_class = function_class + self.type_system_class = type_system_class + self.classes = {} # classdef --> class_name + self.functions = {} # graph --> function_name + self.function_names = {} # graph --> real_name + self.methods = {} # graph --> method_name + self.consts = {} # value --> const_name + self.const_names = set() + self.const_var = Variable("__consts") + self.name_manager = JavascriptNameManager(self) + self.pending_consts = [] + self.cts = type_system_class(self) + + def is_primitive(self, type_): + if type_ in [Void, Bool, Float, Signed, Unsigned, SignedLongLong, UnsignedLongLong, Char, UniChar] or \ + isinstance(type_,ootype.StaticMethod): + return True + return False + + def pending_function(self, graph): + self.pending_node(self.function_class(self, graph)) + + def pending_class(self, classdef): + self.pending_node(Class(self, classdef)) + + def pending_record(self, record): + r = Record(self, record) + self.pending_node(r) + return r.get_name() + + def pending_node(self, node): + if node in self._pending_nodes or node in self._rendered_nodes: + return + self._pending_nodes.add(node) + + def record_function(self, graph, name): + self.functions[graph] = name + + def get_uniquename(self, graph, name): + try: + return self.function_names[graph] + except KeyError: + real_name = self.name_manager.uniquename(name) + self.function_names[graph] = real_name + return real_name + + def record_class(self, classdef, name): + self.classes[classdef] = name + + def graph_name(self, graph): + return self.functions.get(graph, None) + + def class_name(self, classdef): + return self.classes.get(classdef, None) + + def record_const(self, value, retval='name'): + type_ = typeOf(value) + if self.is_primitive(type_): + return None + const = AbstractConst.make(self, value) + try: + return self.consts[const] + except KeyError: + log("New const:%r"%value) + if isinstance(value, ootype._string): + log(value._str) + name = const.get_name() + if name in self.const_names: + name += '__%d' % len(self.consts) + self.consts[const] = name + self.const_names.add(name) + self.pending_consts.append((const,name)) + if retval == 'name': + return name + else: + return const + + def gen_constants(self, ilasm): + ilasm.begin_consts(self.const_var.name) + + try: + while True: + const,name = self.pending_consts.pop() + const.record_fields() + except IndexError: + pass + + + def generate_constants(consts): + all_c = [const for const,name in consts.iteritems()] + rendered = set() + + while len(all_c) > 0: + const = all_c.pop() + if const not in rendered: + if (not hasattr(const,'depends')) or (not const.depends): + yield const,consts[const] + rendered.add(const) + else: + all_c.append(const) + for i in const.depends: + const.depends = None + all_c.append(i) + + # We need to keep track of fields to make sure + # our items appear earlier than us + for const,name in generate_constants(self.consts): + log("Recording %r %r"%(const,name)) + ilasm.load_local(self.const_var) + const.init(ilasm) + ilasm.set_field(None, name) + ilasm.store_void() + const.init_fields(ilasm, self.const_var, name) + #ilasm.field(name, const.get_type(), static=True) + + + def load_const(self, type_, value, ilasm): + if self.is_primitive(type_): + ilasm.load_const(self.cts.primitive_repr(type_, value)) + else: + name = self.record_const(value) + ilasm.load_local(self.const_var) + ilasm.get_field(name) + #assert False, 'Unknown constant %s' % const + + +class AbstractConst(object): + def __init__(self, db, const): + self.db = db + self.const = const + self.cts = db.type_system_class(db) + self.depends = set() + + def make(db, const): + if isinstance(const, ootype._view): + static_type = const._TYPE + const = const._inst + else: + static_type = None + + if isinstance(const, ootype._instance): + return InstanceConst(db, const, static_type) + elif isinstance(const, ootype._list): + return ListConst(db, const) + elif isinstance(const, ootype._record): + return RecordConst(db, const) + elif isinstance(const, ootype._string): + return StringConst(db, const) + else: + assert False, 'Unknown constant: %s %r' % (const, typeOf(const)) + make = staticmethod(make) + + def get_name(self): + pass + + def get_type(self): + pass + + def init(self, ilasm): + pass + + def init_fields(self, ilasm, const_var, name): + pass + + def record_fields(self): + pass + +class InstanceConst(AbstractConst): + def __init__(self, db, obj, static_type): + self.depends = set() + self.db = db + self.cts = db.type_system_class(db) + self.obj = obj + if static_type is None: + self.static_type = obj._TYPE + else: + self.static_type = static_type + self.cts.lltype_to_cts(obj._TYPE) # force scheduling of obj's class + + def __hash__(self): + return hash(self.obj) + + def __eq__(self, other): + return self.obj == other.obj + + def get_name(self): + return self.obj._TYPE._name.replace('.', '_') + + def get_type(self): + return self.cts.lltype_to_cts(self.static_type) + + def init(self, ilasm): + classdef = self.obj._TYPE + ilasm.new(classdef._name.split(".")[-1]) + + def record_fields(self): + # we support only primitives, tuples, strings and lists + for i in self.obj.__dict__: + # FIXME: is this ok? + if i.startswith('o'): + val = self.obj.__dict__[i] + name = self.db.record_const(val,'const') + if name is not None: + self.depends.add(name) + + def init_fields(self, ilasm, const_var, name): + for i in self.obj.__dict__: + # FIXME: is this ok? + if i.startswith('o'): + ilasm.load_local(const_var) + el = self.obj.__dict__[i] + self.db.load_const(typeOf(el), el, ilasm) + ilasm.set_field(None, "%s.%s"%(name, i)) + ilasm.store_void() + #raise NotImplementedError("Default fields of instances") + +class RecordConst(AbstractConst): + def get_name(self): + return "const_tuple" + + def init(self, ilasm): + ilasm.new_obj() + + def record_fields(self): + for i in self.const._items: + name = self.db.record_const(self.const._items[i],'const') + if name is not None: + self.depends.add(name) + + def __hash__(self): + return hash(self.const) + + def __eq__(self, other): + return self.const == other.const + + def init_fields(self, ilasm, const_var, name): + #for i in self.const.__dict__["_items"]: + for i in self.const._items: + ilasm.load_local(const_var) + el = self.const._items[i] + self.db.load_const(typeOf(el), el, ilasm) + ilasm.set_field(None, "%s.%s"%(name, i)) + ilasm.store_void() + +class ListConst(AbstractConst): + + def get_name(self): + return "const_list" + + def init(self, ilasm): + ilasm.new_list() + + def record_fields(self): + for i in self.const._list: + name = self.db.record_const(i,'const') + if name is not None: + self.depends.add(name) + + def __hash__(self): + return hash(self.const) + + def __eq__(self, other): + return self.const == other.const + + def init_fields(self, ilasm, const_var, name): + for i in xrange(len(self.const._list)): + ilasm.load_str("%s.%s"%(const_var.name, name)) + el = self.const._list[i] + self.db.load_const(typeOf(el), el, ilasm) + self.db.load_const(typeOf(i), i, ilasm) + ilasm.list_setitem() + ilasm.store_void() + +class StringConst(AbstractConst): + def get_name(self): + return "const_str" + + def __hash__(self): + return hash(self.const._str) + + def __eq__(self, other): + return self.const._str == other.const._str + + def init(self, ilasm): + ilasm.load_str("'%s'"%self.const._str) + + def init_fields(self, ilasm, const_var, name): + pass + +## ilasm.new('instance void class %s::.ctor()' % classdef._name) +## while classdef is not None: +## for name, (type_, default) in classdef._fields.iteritems(): +## if isinstance(type_, ootype.StaticMethod): +## continue +## elif type_ is ootype.Class: +## value = getattr(self.obj, name) +## self.cts.lltype_to_cts(value._INSTANCE) # force scheduling class generation +## classname = value._INSTANCE._name +## ilasm.opcode('dup') +## ilasm.opcode('ldtoken', classname) +## ilasm.call('class [mscorlib]System.Type class [mscorlib]System.Type::GetTypeFromHandle(valuetype [mscorlib]System.RuntimeTypeHandle)') +## ilasm.opcode('stfld class [mscorlib]System.Type %s::%s' % (classdef._name, name)) +## classdef = classdef._superclass +## Modified: pypy/dist/pypy/translator/js2/function.py ============================================================================== --- pypy/dist/pypy/translator/js2/function.py (original) +++ pypy/dist/pypy/translator/js2/function.py Mon May 29 19:45:52 2006 @@ -14,10 +14,7 @@ from pypy.translator.cli.node import Node from pypy.translator.cli.class_ import Class -from pypy.tool.ansi_print import ansi_log -import py -log = py.log.Producer("cli") -py.log.setconsumer("cli", ansi_log) +from pypy.translator.js2.log import log class LoopFinder: @@ -52,14 +49,15 @@ self.visit_Block(link.target, switches) class Function(Node, Generator): - def __init__(self, db, graph, name = None, is_method = False, is_entrypoint = False ): + def __init__(self, db, graph, name=None, is_method=False, is_entrypoint=False, _class = None): self.db = db self.cts = db.type_system_class(db) self.graph = graph - self.name = name or graph.name + self.name = name or self.db.get_uniquename(self.graph, graph.name) self.is_method = is_method self.is_entrypoint = is_entrypoint self.blocknum = {} + self._class = _class self._set_args() self._set_locals() @@ -78,22 +76,23 @@ def _is_raise_block(self, block): return (not block.exits) and len(block.inputargs) == 2 - def render_block ( self , block ): - for op in block.operations: - self._render_op(op) - def render_block(self, block, stop_block = None): if block is stop_block: return + handle_exc = (block.exitswitch == flowmodel.c_last_exception) + if handle_exc: + self.ilasm.begin_try() + for op in block.operations: self._render_op(op) if len(block.exits) == 0: # return block return_var = block.inputargs[0] - self.load(return_var) - self.ilasm.ret() + if return_var.concretetype is not Void: + self.load(return_var) + self.ilasm.ret() elif block.exitswitch is None: # single exit block assert(len(block.exits) == 1) @@ -101,7 +100,8 @@ self._setup_link(link) self.render_block(link.target, stop_block) elif block.exitswitch is flowmodel.c_last_exception: - raise NotImplementedError("Exception handling") + # we've got exception block + raise NotImplementedError("Exception handling not implemented") else: if self.loops.has_key(block): # we've got loop @@ -132,10 +132,19 @@ if self.db.graph_name(self.graph) is not None and not self.is_method: return # already rendered + if self.is_method: + args = self.args[1:] # self is implicit + else: + args = self.args + self.ilasm = ilasm self.loops = LoopFinder(self.graph.startblock).loops - self.ilasm.begin_function(self.name, self.args, None, None, None) + if self.is_method: + self.ilasm.begin_method(self.name, self._class, args) + else: + self.ilasm.begin_function(self.name, args) + log("loops: %r"%self.loops) self.render_block(self.graph.startblock) ## if self._is_return_block(block): @@ -219,7 +228,7 @@ self.locals = locals def _set_args(self): - args = [arg for arg in self.graph.getargs() if arg.concretetype is not Void] + args = self.graph.getargs() self.args = map(self.cts.llvar_to_cts, args) self.argset = set([argname for argtype, argname in self.args]) @@ -276,27 +285,33 @@ self.db.pending_function(graph) func_sig = self.function_signature(graph) self.ilasm.call(func_sig) + + def call_external(self, name, args): + self.ilasm.call((name, args)) - def call_signature(self, signature): - self.ilasm.call(signature) + #def call_signature(self, signature): + # self.ilasm.call(signature) def cast_to(self, lltype): cts_type = self.cts.lltype_to_cts(lltype, False) self.ilasm.castclass(cts_type) def new(self, obj): - self.ilasm.new(self.cts.ctor_name(obj)) + self.ilasm.new(self.cts.obj_name(obj)) def set_field(self, obj, name): - self.ilasm.set_field(self.field_name(obj,name)) + self.ilasm.set_field(obj, name) + #self.ilasm.set_field(self.field_name(obj,name)) - def get_field(self, obj, name): - self.ilasm.get_field(self.field_name(obj,name)) + def get_field(self, useless_stuff, name): + self.ilasm.get_field(name) def call_method(self, obj, name): - # TODO: use callvirt only when strictly necessary - signature, virtual = self.cts.method_signature(obj, name) - self.ilasm.call_method(signature, virtual) + func_name, signature = self.cts.method_signature(obj, name) + self.ilasm.call_method(obj, name, signature) + + def call_external_method(self, name, arg_len): + self.ilasm.call_method(None, name, [0]*arg_len) def load(self, v): if isinstance(v, flowmodel.Variable): @@ -310,30 +325,46 @@ self.ilasm.load_local(v) elif isinstance(v, flowmodel.Constant): - self._load_const(v) + self.db.load_const(v.concretetype, v.value, self.ilasm) else: assert False - - def _load_const(self, const): - type_ = const.concretetype - if type_ in [ Void , Bool , Float , Signed , Unsigned , SignedLongLong , UnsignedLongLong ]: - self.ilasm.load_const(type_,const.value) - else: - name = self.db.record_const(const.value) - cts_type = self.cts.lltype_to_cts(type_) - self.ilasm.load_set_field(cts_type,name) - #assert False, 'Unknown constant %s' % const - + def store(self, v): if isinstance(v, flowmodel.Variable): if v.concretetype is not Void: self.ilasm.store_local(v) + else: + self.ilasm.store_void() else: assert False def change_name(self, name, to_name): self.ilasm.change_name(name, to_name) - def cast_floor(self): - self.ilasm.cast_floor() + def cast_function(self, name, num): + self.ilasm.cast_function(name, num) + def prefix_op(self, st): + self.ilasm.prefix_op(st) + + def load_str(self, s): + self.ilasm.load_str(s) + + def load_void(self): + self.ilasm.load_void() + + def list_setitem(self, base_obj, item, val): + self.load(base_obj) + self.load(val) + self.load(item) + self.ilasm.list_setitem() + + def list_getitem(self, base_obj, item): + self.load(base_obj) + self.load(item) + self.ilasm.list_getitem() + + def list_resize(self, lst, new_size): + self.load(lst) + self.load(new_size) + self.set_field(None, 'length') Modified: pypy/dist/pypy/translator/js2/js.py ============================================================================== --- pypy/dist/pypy/translator/js2/js.py (original) +++ pypy/dist/pypy/translator/js2/js.py Mon May 29 19:45:52 2006 @@ -21,6 +21,7 @@ from pypy.translator.js2.jts import JTS from pypy.translator.js2.opcodes import opcodes from pypy.translator.js2.function import Function +from pypy.translator.js2.database import LowLevelDatabase from pypy.translator.cli.gencli import GenCli @@ -33,10 +34,25 @@ class JS(object): def __init__(self, translator, functions=[], stackless=False, compress=False, logging=False): self.cli = GenCli(udir, translator, type_system_class = JTS, opcode_dict = opcodes,\ - name_suffix = '.js', function_class = Function) + name_suffix = '.js', function_class = Function, database_class = LowLevelDatabase) self.translator = translator def write_source(self): + + # write down additional functions + # FIXME: when used with browser option it should probably + # not be used as inlined, rather another script to load + # this is just workaround + self.cli.generate_source(AsmGen) self.filename = self.cli.tmpfile + + data = self.filename.open().read() + src_filename = _path_join(os.path.dirname(__file__), 'src', 'misc.js') + f = self.cli.tmpfile.open("w") + s = open(src_filename).read() + f.write(s) + f.write(data) + f.close() + return self.cli.tmpfile Modified: pypy/dist/pypy/translator/js2/jts.py ============================================================================== --- pypy/dist/pypy/translator/js2/jts.py (original) +++ pypy/dist/pypy/translator/js2/jts.py Mon May 29 19:45:52 2006 @@ -3,6 +3,15 @@ """ from pypy.rpython.ootypesystem import ootype +from pypy.rpython.lltypesystem import lltype +from pypy.translator.cli import oopspec + +from pypy.rpython.lltypesystem.lltype import Signed, Unsigned, Void, Bool, Float +from pypy.rpython.lltypesystem.lltype import SignedLongLong, UnsignedLongLong, Primitive +from pypy.rpython.lltypesystem.lltype import Char, UniChar +from pypy.rpython.ootypesystem.ootype import String, _string, List, StaticMethod + +from pypy.translator.js2.log import log class JTS(object): """ Class implementing JavaScript type system @@ -11,24 +20,82 @@ def __init__(self, db): self.db = db + def __class(self, name): + return name.split(".")[-1] + def llvar_to_cts(self, var): return 'var ', var.name + def lltype_to_cts(self, t): + if isinstance(t, ootype.Instance): + self.db.pending_class(t) + return self.__class(t._name) + elif isinstance(t, ootype.List): + return "Array" + elif isinstance(t, lltype.Primitive): + return "var" + elif isinstance(t, ootype.Record): + return "Object" + elif isinstance(t, ootype.String.__class__): + return '""' + #return "var" + raise NotImplementedError("Type %r" % (t,)) + def graph_to_signature(self, graph, is_method = False, func_name = None): - ret_type, ret_var = self.llvar_to_cts(graph.getreturnvar()) - func_name = func_name or graph.name + func_name = func_name or self.db.get_uniquename(graph,graph.name) - args = [arg for arg in graph.getargs() if arg.concretetype is not ootype.Void] + args = graph.getargs() if is_method: args = args[1:] - #arg_types = [self.lltype_to_cts(arg.concretetype) for arg in args] - #arg_list = ', '.join(arg_types) - return func_name,args - def lltype_to_cts(self, t, include_class=True): - return 'var' + def method_signature(self, obj, name): + # TODO: use callvirt only when strictly necessary + if isinstance(obj, ootype.Instance): + owner, meth = obj._lookup(name) + class_name = obj._name + return self.graph_to_signature(meth.graph, True, class_name) + + elif isinstance(obj, ootype.BuiltinType): + meth = oopspec.get_method(obj, name) + class_name = self.lltype_to_cts(obj) + #arg_list = ', '.join(arg_types) + return class_name,meth.ARGS + else: + assert False + + def obj_name(self, obj): + return self.lltype_to_cts(obj) + + def primitive_repr(self, _type, v): + if _type is Bool: + if v == False: + val = 'false' + else: + val = 'true' + elif _type is Void: + val = 'undefined' + elif isinstance(_type,String.__class__): + val = '%r'%v._str + elif isinstance(_type,List): + # FIXME: It's not ok to use always empty list + val = "[]" + elif isinstance(_type,StaticMethod): + val = v._name + elif _type is UniChar or _type is Char: + #log("Constant %r"%v) + val = '"%s"'%str(v) + elif isinstance(_type,Primitive): + #log("Type: %r"%_type) + val = str(v) + else: + assert False, "Unknown constant %r"%_type + val = str(v) + return val + + #def lltype_to_cts(self, t, include_class=True): + # return 'var' ## if isinstance(t, ootype.Instance): ## self.db.pending_class(t) ## return self.__class(t._name, include_class) Modified: pypy/dist/pypy/translator/js2/opcodes.py ============================================================================== --- pypy/dist/pypy/translator/js2/opcodes.py (original) +++ pypy/dist/pypy/translator/js2/opcodes.py Mon May 29 19:45:52 2006 @@ -3,20 +3,128 @@ """ from pypy.translator.cli.metavm import PushArg, PushAllArgs, StoreResult,\ - InstructionList, New, SetField, GetField, CallMethod, RuntimeNew, Call, MicroInstruction + InstructionList, New, SetField, GetField, RuntimeNew, MicroInstruction DoNothing = [PushAllArgs] +from pypy.translator.js2._builtin import Builtins +from pypy.translator.js2.log import log + +##class _GetField(MicroInstruction): +## def render(self, generator, op): +## this, field = op.args +## generator.load(this) +## generator.get_field(this.concretetype, field.value) + class _SameAs(MicroInstruction): def render(self, generator, op): generator.change_name(op.result, op.args[0]) -class _CastFloor(MicroInstruction): +class _CastFun(MicroInstruction): + def __init__(self, name, num): + self.name = name + self.num = num + + def render(self, generator, op): + generator.cast_function(self.name, self.num) + +class _Prefix(MicroInstruction): + def __init__(self, st): + self.st = st + + def render(self, generator, op): + generator.prefix_op(self.st) + +class _NotImplemented(MicroInstruction): + def __init__(self, reason): + self.reason = reason + + def render(self, generator, op): + raise NotImplementedError(self.reason) + +class _CastString(MicroInstruction): + def render(self, generator, op): + this = op.args[0] + generator.load(this) + generator.call_external_method("toString", 0) + +class _Call(MicroInstruction): def render(self, generator, op): - generator.cast_floor() + graph = op.args[0].value.graph + #method_name = oopspec.get_method_name(graph, op) + #if method_name is None: + bt = Builtins.map_builtin_function(op.args[0], self, op.args, generator) + if bt: + builtin, is_property = bt + self._render_builtin(generator, builtin, op.args, is_property) + log("Suggested builtin %r %r"%(bt, is_property)) + if bt is None: + self._render_function(generator, graph, op.args) + #else: + # self._render_method(generator, method_name, op.args[1:]) + + def _render_builtin(self, generator, builtin, args, is_property): + if not is_property: + for func_arg in args[1:]: # push parameters + generator.load(func_arg) + generator.call_external(builtin, args[1:]) + else: + generator.load_str(builtin) + + def _render_builtin_method(self, generator, builtin, args, is_property): + if not is_property: + for func_arg in args: + generator.load(func_arg) + generator.call_external_method(builtin, len(args)-1) + else: + generator.load(args[0]) + generator.get_field(None, builtin) + + def _render_function(self, generator, graph, args): + #func_sig = generator.function_signature(graph) + for func_arg in args[1:]: # push parameters + generator.load(func_arg) + generator.call_graph(graph) + + # Various low level function-to-operator mappings + + def list_ll_setitem(self, base_obj, args, generator): + generator.list_setitem(base_obj, args[1], args[2]) + + def list_ll_getitem(self, base_obj, args, generator): + generator.list_getitem(base_obj, args[1]) + + def list_ll_resize(self, base_obj, args, generator): + generator.list_resize(base_obj, args[1]) + + def do_nothing(self, base_obj, args, generator): + generator.load_void() + + def equal(self, base_obj, args, generator): + generator.load(args[1]) + generator.load(args[2]) + generator.emit("==") + + def _render_method(self, generator, method_name, args): + this = args[0] + bt = Builtins.map_builtin_method(this, method_name, args, self, generator) + if bt: + function,is_property = bt + self._render_builtin_method(generator, function, args, is_property) + if bt is None: + for arg in args: # push parametes + generator.load(arg) + generator.call_method(this.concretetype, method_name) -CastFloor = [PushAllArgs, _CastFloor()] +class _CallMethod(_Call): + def render(self, generator, op): + method = op.args[0] + self._render_method(generator, method.value, op.args[1:]) + +Call = _Call() +CallMethod = _CallMethod() CopyName = [PushAllArgs, _SameAs ()] +CastString = _CastString() SameAs = CopyName opcodes = {'int_mul': '*', @@ -81,9 +189,35 @@ 'ptr_eq': '==', 'ptr_ne': '!=', + + 'bool_not': [PushAllArgs,_Prefix('!')], + 'int_neg': [PushAllArgs,_Prefix('-')], + 'int_invert': [PushAllArgs,_Prefix('~')], + 'float_neg': [PushAllArgs,_Prefix('-')], + 'float_pow': [PushAllArgs,_CastFun('Math.pow',2)], + 'int_abs': [PushAllArgs,_CastFun('Math.abs',1)], + 'float_abs': [PushAllArgs,_CastFun('Math.abs',1)], + + 'int_is_true': [PushAllArgs,_Prefix('!!')], + 'uint_is_true': [PushAllArgs,_Prefix('!!')], + 'float_is_true': [PushAllArgs,_Prefix('!!')], + 'direct_call' : [Call], + 'indirect_call' : [_NotImplemented("Indirect call not implemented")], 'same_as' : SameAs, + 'new' : [New], + + # objects + + 'oosetfield' : [SetField], + 'oogetfield' : [GetField], + 'oosend' : [CallMethod], + 'ooupcast' : [_NotImplemented("Inheritance not implemented (ooupcast)")], + 'oodowncast' : [_NotImplemented("Inheritance not implemented (oodowncast)")], + 'oononnull' : [PushAllArgs,_Prefix('!!')], + 'oostring' : [CastString], + 'oois' : '==', # FIXME: JS does not have real equal # when casting from bool we want that every truth value is casted # to 1: we can't simply DoNothing, because the CLI stack could # contains a truth value not equal to 1, so we should use the !=0 @@ -100,8 +234,8 @@ 'cast_int_to_longlong': CopyName, 'cast_uint_to_int': CopyName, 'cast_uint_to_float': CopyName, - 'cast_float_to_int': CastFloor, - 'cast_float_to_uint': CastFloor, + 'cast_float_to_int': [PushAllArgs,_CastFun("Math.floor",1)], + 'cast_float_to_uint': [PushAllArgs,_CastFun("Math.floor",1)], 'truncate_longlong_to_int': CopyName, } Modified: pypy/dist/pypy/translator/js2/support.py ============================================================================== --- pypy/dist/pypy/translator/js2/support.py (original) +++ pypy/dist/pypy/translator/js2/support.py Mon May 29 19:45:52 2006 @@ -2,9 +2,9 @@ #from pypy.translator.js2.optimize import is_optimized_function class JavascriptNameManager(NameManager): - def __init__(self, js): + def __init__(self, db): NameManager.__init__(self) - self.js = js + self.db = db self.reserved = {} #http://javascript.about.com/library/blreserved.htm Modified: pypy/dist/pypy/translator/js2/test/runtest.py ============================================================================== --- pypy/dist/pypy/translator/js2/test/runtest.py (original) +++ pypy/dist/pypy/translator/js2/test/runtest.py Mon May 29 19:45:52 2006 @@ -41,8 +41,8 @@ self.js.write_source() def _conv(self, v): - if isinstance(v, str): - return "{hash:0, chars:'%s'}" % v + #if isinstance(v, str): + # return "{hash:0, chars:'%s'}" % v return str(v).lower() def __call__(self, *kwds): Added: pypy/dist/pypy/translator/js2/test/test_class.py ============================================================================== --- (empty file) +++ pypy/dist/pypy/translator/js2/test/test_class.py Mon May 29 19:45:52 2006 @@ -0,0 +1,94 @@ +from __future__ import division +import py + +from pypy.translator.js2.test.runtest import compile_function +from pypy.translator.llvm.test import llvmsnippet + +class TestClass(object): + def test_classsimple(self): + f = compile_function(llvmsnippet.class_simple, []) + assert f() == 14 + + def test_classsimple1(self): + f = compile_function(llvmsnippet.class_simple1, [int]) + assert f(2) == 10 + + def test_id_int(self): + #py.test.skip("Full list support not implemented") + f = compile_function(llvmsnippet.id_int, [int]) + for i in range(1, 20): + assert f(i) == i + + def test_classsimple2(self): + f = compile_function(llvmsnippet.class_simple2, [int]) + assert f(2) == 10 + + def test_inherit1(self): + py.test.skip("Inheritance not implemented") + #py.test.skip("issue 'null' for Ptr's? or recurse into Ptr.TO?) see: opwriter.py") + f = compile_function(llvmsnippet.class_inherit1, []) + assert f() == 11 + + def test_inherit2(self): + py.test.skip("Inheritance not implemented") + #py.test.skip("issue 'null' for Ptr's? or recurse into Ptr.TO?) see: opwriter.py") + f = compile_function(llvmsnippet.class_inherit2, []) + assert f() == 1 + + def test_method_of_base_class(self): + py.test.skip("Inheritance not implemented") + #py.test.skip("issue 'null' for Ptr's? or recurse into Ptr.TO?) see: opwriter.py") + f = compile_function(llvmsnippet.method_of_base_class, []) + assert f() == 14 + + def test_attribute_from_base_class(self): + py.test.skip("Inheritance not implemented") + f = compile_function(llvmsnippet.attribute_from_base_class, []) + assert f() == 4 + + def test_direct_call_of_virtual_method(self): + py.test.skip("Inheritance not implemented") + #py.test.skip("issue 'null' for Ptr's? or recurse into Ptr.TO?) see: opwriter.py") + f = compile_function(llvmsnippet.direct_call_of_virtual_method, []) + assert f() == 14 + + def test_flow_type(self): + py.test.skip("Inheritance not implemented") + f = compile_function(llvmsnippet.flow_type, []) + assert f() == 16 + + def test_merge_class(self): + py.test.skip("Inheritance not implemented") + f = compile_function(llvmsnippet.merge_classes, [bool]) + assert f(True) == 1 + assert f(False) == 2 + + def test_attribute_instance(self): + py.test.skip("Inheritance not implemented") + f = compile_function(llvmsnippet.attribute_instance, [bool]) + assert f(True) == 1 + assert f(False) == 2 + + def DONTtest_global_instance(self): #issue we restart every test with a fresh set of globals + f = compile_function(llvmsnippet.global_instance, [int]) + assert f(-1) == llvmsnippet.global_instance(-1) + for i in range(20): + x = f(i) + y = llvmsnippet.global_instance(i) + assert x == y + + def test_getset(self): + #py.test.skip("Basic arguments of const objects not implemented") + f = compile_function(llvmsnippet.testgetset, [int]) + assert f(15) == 25 + + def test_call_degrading_func(self): + py.test.skip("Inheritance not implemented") + f = compile_function(llvmsnippet.call_degrading_func, [bool]) + assert f(True) == llvmsnippet.call_degrading_func(True) + assert f(False) == llvmsnippet.call_degrading_func(False) + + def test_circular_classdef(self): + py.test.skip("Inheritance not implemented") + f = compile_function(llvmsnippet.circular_classdef, []) + assert f() == 10 Added: pypy/dist/pypy/translator/js2/test/test_exc_operation.py ============================================================================== --- (empty file) +++ pypy/dist/pypy/translator/js2/test/test_exc_operation.py Mon May 29 19:45:52 2006 @@ -0,0 +1,195 @@ +import py +import sys +from pypy.translator.js2.test.runtest import compile_function +from pypy.rpython.rarithmetic import r_uint, ovfcheck, ovfcheck_lshift +from pypy.translator.test import snippet + +py.test.skip("Exception work in progress") + +def test_zerodiv_int(): + def zerodiv_int(n): + try: + r=100/n + except ZeroDivisionError: + return n+7 + return r + f = compile_function(zerodiv_int, [int]) + for i in (-50,0,50): + assert f(i) == zerodiv_int(i) + +def test_zerodiv_uint(): + def zerodiv_uint(n): + try: + r=100/n + except ZeroDivisionError: + return n+7 + return r + f = compile_function(zerodiv_uint, [r_uint]) + for i in (0,50,100): + assert f(i) == zerodiv_uint(i) + +def test_zerodivrem_int(): + def zerodivrem_int(n): + try: + r=100%n + except ZeroDivisionError: + return n+7 + return r + f = compile_function(zerodivrem_int, [int]) + for i in (-50,0,50): + assert f(i) == zerodivrem_int(i) + +def test_zerodivrem_uint(): + def zerodivrem_uint(n): + try: + r=100%n + except ZeroDivisionError: + return n+7 + return r + f = compile_function(zerodivrem_uint, [r_uint]) + for i in (0,50,100): + assert f(i) == zerodivrem_uint(i) + +def DONTtest_neg_int_ovf(): #issue with Javascript Number() having a larger range + def neg_int_ovf(n): + try: + r=ovfcheck(-n) + except OverflowError: + return 123 + return r + f = compile_function(neg_int_ovf, [int]) + for i in (-sys.maxint-1, -sys.maxint, 0, sys.maxint-1, sys.maxint): + assert f(i) == neg_int_ovf(i) + +def DONTtest_abs_int_ovf(): #issue with Javascript Number() having a larger range + def abs_int_ovf(n): + try: + r=ovfcheck(abs(n)) + except OverflowError: + return 123 + return r + f = compile_function(abs_int_ovf, [int]) + for i in (-sys.maxint-1, -sys.maxint, 0, sys.maxint-1, sys.maxint): + assert f(i) == abs_int_ovf(i) + +############################ + +#raises(...) fails because we do'nt reraise javascript exceptions on the python level + +def DONTtest_int_ovf(): #issue with Javascript Number() having a larger range + def int_ovf_fn(i): + try: + return snippet.add_func(i) + except OverflowError: + return 123 + except: + return 1234 + fn = compile_function(int_ovf_fn, [int]) + for i in (-sys.maxint-1, -1, 0, 1, sys.maxint): + assert fn(i) == int_ovf_fn(i) + +def test_int_div_ovf_zer(): + def int_div_ovf_zer_fn(i): + try: + return snippet.div_func(i) + except OverflowError: + return 123 + except ZeroDivisionError: + return 1234 + except: + return 12345 + fn = compile_function(int_div_ovf_zer_fn, [int]) + for i in (-sys.maxint-1, -1, 0, 1, sys.maxint): + assert fn(i) == int_div_ovf_zer_fn(i) + +def DONTtest_int_mod_ovf_zer(): #issue with Javascript Number() having a larger range + def int_mod_ovf_zer_fn(i): + try: + return snippet.mod_func(i) + except OverflowError: + return 123 + except ZeroDivisionError: + return 1234 + except: + return 12345 + fn = compile_function(int_mod_ovf_zer_fn, [int]) + for i in (-sys.maxint-1, -1, 0, 1, sys.maxint): + assert fn(i) == int_mod_ovf_zer_fn(i) + +def DONTtest_int_rshift_val(): #issue with Javascript Number() having a larger range + def rshift_fn(i): + try: + return snippet.rshift_func(i) + except ValueError: + return 123 + except: + return 1234 + fn = compile_function(rshift_fn, [int]) + for i in (-sys.maxint-1, -1, 0, 1, sys.maxint): + assert fn(i) == rshift_fn(i) + +def test_int_lshift_ovf_val(): + def lshift_fn(i): + try: + return snippet.lshift_func(i) + except ValueError: + return 123 + except OverflowError: + return 1234 + except: + return 12345 + fn = compile_function(lshift_fn, [int]) + for i in (-sys.maxint-1, -1, 0, 1, sys.maxint): + assert fn(i) == lshift_fn(i) + +def test_uint_arith(): + py.test.skip("unsigned number becomes negative because we should cast to unsigned when necessary") + def fn(i): + try: + return ~(i*(i+1))/(i-1) + except ZeroDivisionError: + return r_uint(91872331) + f = compile_function(fn, [r_uint]) + for value in range(15): + i = r_uint(value) + assert f(i) == fn(i) + +def test_int_add_ovf(): + def add_func(i): + try: + return ovfcheck(i + 1) + except OverflowError: + return 123 + f = compile_function(add_func, [int]) + assert f(0) == add_func(0) + assert f(0) == 1 + assert f(sys.maxint) == add_func(sys.maxint) + assert f(sys.maxint) == 123 + +def test_int_sub_ovf(): + def sub_func(i): + try: + return ovfcheck(i - 1) + except OverflowError: + return 123 + n_ovf = 0 + f = compile_function(sub_func, [int]) + for i in (-1, 0, 1, sys.maxint, -sys.maxint, -sys.maxint-1): + result = f(i) + assert result == sub_func(i) + n_ovf += result == 123 + assert n_ovf == 1 + +#As JavaScript uses floating-point numbers the accuracy is only assured +#for integers between: -9007199254740992 (-2^53) and 9007199254740992 (2^53) +def DONTtest_shift_with_overflow(): #issue with Javascript Number() having a larger range + def shiftleft(x, y): + return x << y + def shiftright(x, y): + return x >> y + shl = compile_function(shiftleft , [int, int]) + shr = compile_function(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 Added: pypy/dist/pypy/translator/js2/test/test_exception.py ============================================================================== --- (empty file) +++ pypy/dist/pypy/translator/js2/test/test_exception.py Mon May 29 19:45:52 2006 @@ -0,0 +1,271 @@ +import py + +from pypy.translator.js2.test.runtest import compile_function +from pypy.translator.test.snippet import try_raise_choose +from pypy.rpython.rarithmetic import r_uint, ovfcheck, ovfcheck_lshift + +import sys + +py.test.skip("Exception work in progress") + +class TestException(Exception): + pass + +class MyException(Exception): + def __init__(self, n): + self.n = n + +def getitem(l, i): #LookupError, KeyError + if not isinstance(i, int): + raise TypeError + if i < 0: + i = len(l) - i + if i>= len(l): + raise IndexError + return l[i] + +def test_simple1(): + def raise_(i): + if i: + raise TestException() + else: + return 3 + def fn(i): + try: + a = raise_(i) + 11 + b = raise_(i) + 12 + c = raise_(i) + 13 + return a+b+c + except TestException: + return 7 + else: + return 3 + f = compile_function(fn, [int]) + assert f(0) == fn(0) + assert f(1) == fn(1) + +def test_simple2(): + def fn(n): + lst = range(10) + try: + getitem(lst,n) + except: + return 2 + return 4 + f = compile_function(fn, [int]) + assert f(-1) == fn(-1) + assert f( 0) == fn( 0) + assert f(10) == fn(10) + +def test_simple3(): + def raise_(i): + if i == 0: + raise TestException() + elif i == 1: + raise MyException(42) + else: + return 3 + def fn(i): + try: + a = raise_(i) + 11 + b = raise_(i) + 12 + c = raise_(i) + 13 + return a+b+c + except TestException: + return 7 + except MyException: + return 123 + except: + return 22 + return 66 + f = compile_function(fn, [int]) + assert f(0) == fn(0) + assert f(1) == fn(1) + assert f(2) == fn(2) + +def test_pass_exc(): + def fn(n): + lst = range(10) + try: + getitem(lst,n) + except: + pass + return 4 + f = compile_function(fn, [int]) + assert f(-1) == fn(-1) + assert f( 0) == fn( 0) + assert f(10) == fn(10) + +def test_reraise1(): + def fn2(n): + lst = range(10) + try: + getitem(lst,n) + except: + raise + return 4 + def fn(n): + try: + return fn2(n) + except: + return 123 + f = compile_function(fn, [int]) + assert f(-1) == 123 + assert f(-1) == fn(-1) + assert f( 0) == fn( 0) + assert f(10) == 123 + assert f(10) == fn(10) + +def test_reraise2(): + def fn2(n): + lst = range(10) + try: + getitem(lst,n) + except Exception, e: + raise e + return 4 + def fn(n): + try: + return fn2(n) + except: + return 123 + f = compile_function(fn, [int]) + assert f(-1) == 123 + assert f(-1) == fn(-1) + assert f( 0) == fn( 0) + assert f(10) == 123 + assert f(10) == fn(10) + +def test_simple_exception(): + def fn(n): + lst = range(10) + try: + getitem(lst,n) + except IndexError: + return 2 + return 4 + f = compile_function(fn, [int]) + for i in range(10): + assert f(i) == fn(i) + for i in range(10, 20): + assert f(i) == fn(i) + +def test_two_exceptionsA(): + def fn(n): + lst = range(10) + try: + getitem(lst,n) + except IndexError: + return 2 + except KeyError: + return 3 + return 4 + f = compile_function(fn, [int]) + for i in range(10): + assert f(i) == fn(i) + for i in range(10, 20): + assert f(i) == fn(i) + +def test_catch_base_exception(): + def fn(n): + lst = range(10) + try: + getitem(lst,n) + except LookupError: + return 2 + return 4 + f = compile_function(fn, [int]) + for i in range(10): + assert f(i) == fn(i) + for i in range(10, 20): + assert f(i) == fn(i) + +def test_catches(): + def raises(i): + if i == 3: + raise MyException, 12 + if i == 4: + raise IndexError + if i > 5: + raise MyException(i) + return 1 + def fn(i): + try: + return raises(i) + except MyException, e: + return e.n + except: + return 123 + f = compile_function(fn, [int]) + assert f(1) == fn(1) + assert f(2) == fn(2) + assert f(3) == fn(3) + #py.test.raises(RuntimeError, "f(4)") #XXX would like to test: py.test.not_raises(....) + assert f(5) == fn(5) + assert f(6) == fn(6) + assert f(13) == fn(13) + +def test_try_raise_choose(): + f = compile_function(try_raise_choose, [int]) + for i in [-1, 0, 1, 2]: + assert f(i) == i + +def test_two_exceptionsB(): + def fn1(): + raise Exception + def fn2(): + return 10 + def two_exceptionsB(): + r = 50 + try: + fn1() + r += 1 + except: + r += 100 + try: + r += fn2() + except: + r += 300 + r += fn2() + return r + f = compile_function(two_exceptionsB, []) + assert f() == two_exceptionsB() + +def test_raise_outside_testfn(): + def raiser(n): + if n < 0: + raise ValueError("hello") + else: + raise MyException("world") + + def intermediate(n): + raiser(n) + + def testfn(n): + try: + intermediate(n) + except ValueError: + return 1 + except Exception: + return 2 + return 0 + + saved = no_magic() + try: + f = compile_function(testfn, [int]) + assert f(1) == testfn(1) + assert f(-1) == testfn(-1) + finally: + restore_magic(saved) + +def no_magic(): + import __builtin__ + try: + py.magic.revert(__builtin__, 'AssertionError') + return True + except ValueError: + return False + +def restore_magic(saved): + if saved: + py.magic.invoke(assertion=True) Added: pypy/dist/pypy/translator/js2/test/test_genllvm.py ============================================================================== --- (empty file) +++ pypy/dist/pypy/translator/js2/test/test_genllvm.py Mon May 29 19:45:52 2006 @@ -0,0 +1,413 @@ +from __future__ import division + +import sys +import py + +from pypy.rpython.rarithmetic import r_uint +from pypy.translator.js2.test.runtest import compile_function + +def test_simple_function_pointer(): + py.test.skip("ootypesystem problems with lists") + def f1(x): + return x + 1 + def f2(x): + return x + 2 + + l = [f1, f2] + + def pointersimple(i): + return l[i](i) + + f = compile_function(pointersimple, [int]) + assert f(0) == pointersimple(0) + assert f(1) == pointersimple(1) + +def test_return1(): + def simple1(): + return 1 + f = compile_function(simple1, []) + assert f() == 1 + +def test_invoke_function_pointer(): + py.test.skip("ootypesystem problems with lists") + def f1(x): + return x + 1 + def f2(x): + return x + 2 + + l = [f1, f2] + + def invokepointer(i): + try: + return l[i](i) + except: + return 123 + + f = compile_function(invokepointer, [int]) + assert f(0) == invokepointer(0) + assert f(1) == invokepointer(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 + +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 += x % i + x += i + 1 * i // i - 1 + return int(x+0.0001) + f = compile_function(ops, [int]) + assert f(1) == ops(1) + assert f(2) == ops(2) + +def test_uint_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 += x % i + x += i + 1 * i // i - 1 + return int(x+0.0001) + f = compile_function(ops, [r_uint]) + assert f(1) == ops(1) + assert f(2) == ops(2) + +def test_float_ops(): + def ops(flt): + x = 0 + x += flt < flt + x += flt <= flt + x += flt == flt + x += flt != flt + x += flt >= flt + x += flt > flt + x += int(flt + 1 * flt / flt - 1) + return x + f = compile_function(ops, [float]) + assert f(1) == ops(1) + assert f(2) == ops(2) + +def test_while_loop(): + def factorial(i): + r = 1 + while i>1: + r *= i + i -= 1 + return r + f = compile_function(factorial, [int]) + assert factorial(4) == 24 + assert factorial(5) == 120 + f = compile_function(factorial, [float]) + assert factorial(4.) == 24. + assert factorial(5.) == 120. + +def test_return_void(): + def return_void(i): + return None + def call_return_void(i): + return_void(i) + return 1 + f = compile_function(call_return_void, [int]) + assert f(10) == 1 + +def test_break_while_loop(): + def factorial(i): + r = 1 + while 1: + if i<=1: + break + r *= i + i -= 1 + return r + f = compile_function(factorial, [int]) + assert factorial(4) == 24 + assert factorial(5) == 120 + +def test_primitive_is_true(): + def var_is_true(v): + return bool(v) + f = compile_function(var_is_true, [int]) + assert f(256) + assert not f(0) + f = compile_function(var_is_true, [r_uint]) + assert f(r_uint(256)) + assert not f(r_uint(0)) + f = compile_function(var_is_true, [float]) + assert f(256.0) + assert not f(0.0) + +def test_function_call(): + def callee(): + return 1 + def caller(): + return 3 + callee() + f = compile_function(caller, []) + assert f() == 4 + +def test_recursive_call(): + py.test.skip("Recursion support is very limited") + 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 + +def test_tuple_getitem(): + def tuple_getitem(i): + l = (4,5,i) + return l[1] + f = compile_function(tuple_getitem, [int]) + assert f(1) == tuple_getitem(1) + +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 + +def test_prebuilt_tuples(): + t1 = (1,2,3,4) + t2 = (5,6,7,8) + def callee_tuple(t): + return t[0] + def caller_tuple(i): + if i: + return callee_tuple(t1) + i + else: + return callee_tuple(t2) + i + f = compile_function(caller_tuple, [int]) + assert f(0) == 5 + assert f(1) == 2 + +def test_pbc_fns(): + py.test.skip("Indirect call not implemented") + def f2(x): + return x+1 + def f3(x): + return x+2 + def g(y): + if y < 0: + f = f2 + else: + f = f3 + return f(y+3) + f = compile_function(g, [int]) + assert f(-1) == 3 + assert f(0) == 5 + +def test_simple_chars(): #XXX test this also without optimize_call(...) + #py.test.skip("Method mapping not implemented") + def char_constant2(s): + s = s + s + s + return len(s + '.') + def char_constant(): + return char_constant2("kk") + f = compile_function(char_constant, []) + assert f() == 7 + +def test_list_getitem(): + #py.test.skip("List suuport") + def list_getitem(i): + l = [1,2,i+1] + return l[i] + f = compile_function(list_getitem, [int]) + assert f(0) == 1 + assert f(1) == 2 + assert f(2) == 3 + +def test_list_list_getitem(): + #py.test.skip("List support") + def list_list_getitem(): + l = [[1]] + return l[0][0] + f = compile_function(list_list_getitem, []) + assert f() == 1 + +def test_list_getitem_pbc(): + #py.test.skip("pbc support") + l = [1,2] + def list_getitem_pbc(i): + return l[i] + f = compile_function(list_getitem_pbc, [int]) + assert f(0) == 1 + assert f(1) == 2 + +def test_list_list_getitem_pbc(): + #py.test.skip("pbc support") + l = [[0, 1], [0, 1]] + def list_list_getitem_pbc(i): + return l[i][i] + f = compile_function(list_list_getitem_pbc, [int]) + assert f(0) == 0 + assert f(1) == 1 + +def test_list_basic_ops(): + #py.test.skip("List support") + def list_basic_ops(i, j): + l = [1,2,3] + l.insert(0, 42) + del l[1] + l.append(i) + listlen = len(l) + l.extend(l) + del l[listlen:] + l += [5,6] + l[1] = i + return l[j] + f = compile_function(list_basic_ops, [int, int]) + for i in range(6): + for j in range(6): + assert f(i,j) == list_basic_ops(i,j) + +def test_string_simple(): + #py.test.skip("ord semantics") + def string_simple(i): + return ord(str(i)) + f = compile_function(string_simple, [int]) + assert f(3) + +def test_string_simple_ops(): + py.test.skip("ord semantics") + def string_simple_ops(i): + res = 0 + s = str(i) + s2 = s + s + s + s + s3 = s + s + s + s + res += s != s2 + res += s2 == s3 + res += ord(s) + return res + f = compile_function(string_simple_ops, [int]) + assert f(5) == ord('5') + 2 + +def test_string_getitem1(): + l = "Hello, World" + def string_getitem1(i): + return l[i] + f = compile_function(string_getitem1, [int]) + assert f(0) == "H" + +def test_string_getitem2(): + def string_test(i): + l = "Hello, World" + return l[i] + f = compile_function(string_test, [int]) + assert f(0) == "H" + +def test_list_of_string(): + a = ["hello", "world"] + def string_simple(i, j, k, l): + s = a[i][j] + a[k][l] + return s[0] + s[1] + f = compile_function(string_simple, [int, int, int, int]) + assert f(0, 0, 1, 4) == 'hd' + +def test_attrs_class(): + class MyBase: + pass + def attrs_class(a): + obj = MyBase() + obj.z = a + return obj.z * 4 + f = compile_function(attrs_class, [int]) + assert f(4) == 16 + +def test_attrs_class_pbc(): +# py.test.skip("pbc support") + class MyBase: + pass + obj = MyBase() + obj.z = 4 + def attrs_class_pbc(): + return obj.z * 4 + f = compile_function(attrs_class_pbc, []) + assert f() == 16 + +def test_method_call(): + class MyBase: + def m(self): return self.z + obj = MyBase() + obj.z = 4 + def method_call(): + return obj.m() + f = compile_function(method_call, []) + assert f() == 4 + +def test_dict_creation(): + py.test.skip("Dict support not implemented") + d = {'hello' : 23, + 'world' : 21} + l = ["hello", "world"] + def createdict(i, j): + return d[l[i]] + d[l[j]] + assert createdict(0,1) == 44 + f = compile_function(createdict, [int, int]) + assert f(0,1) == createdict(0,1) + +def test_closure(): + #py.test.skip("issue 'null' for Ptr's? or recurse into Ptr.TO?) see: opwriter.py") + py.test.skip("closure support") + class A: + def set(self, x): + self.x = x + def get(self): + return self.x + class B(A): + def get(self): + return A.get(self) * 2 + a = A() + b = B() + def createfn(y): + z = 42 + def fn(x): + return x + y + z + a.get() + b.get() + f2 = lambda: A.get(b) + def getfn(x): + if x % 2: + f = A.get + else: + f = B.get + return f + def proxy(s): + f1 = s.get + t = 0 + for ii in range(5): + f3 = getfn(ii) + t += f1() + t += f2() + t += f3(s) + return t + setattr(B, "f2", proxy) + return fn + fn = createfn(10) + def testf(x): + a.set(10) + b.set(25) + return fn(x) + b.get() + b.f2() + f = compile_function(testf, [int]) + assert f(1) == testf(1) + assert f(2) == testf(2) Added: pypy/dist/pypy/translator/js2/test/test_genllvm1.py ============================================================================== --- (empty file) +++ pypy/dist/pypy/translator/js2/test/test_genllvm1.py Mon May 29 19:45:52 2006 @@ -0,0 +1,93 @@ +from __future__ import division +import sys + +import autopath +import py + +from pypy.objspace.flow.model import Constant, Variable +from pypy.translator.js2.test.runtest import compile_function +from pypy.translator.llvm.test import llvmsnippet + +class TestGenLLVM(object): + def test_simple1(self): + f = compile_function(llvmsnippet.simple1, []) + assert f() == 1 + + def test_simple2(self): + f = compile_function(llvmsnippet.simple2, []) + assert f() == False + + def test_simple4(self): + f = compile_function(llvmsnippet.simple4, []) + assert f() == 4 + + def test_simple5(self): + f = compile_function(llvmsnippet.simple5, [int]) + assert f(1) == 12 + assert f(0) == 13 + + def test_ackermann(self): + py.test.skip("Too much recursion") + f = compile_function(llvmsnippet.ackermann, [int, int]) + for i in range(4): # (otherwise too much recursion) max 4 in Safari, max 7 in Firefox, IE allows more recursion + assert f(0, i) == i + 1 + assert f(1, i) == i + 2 + assert f(2, i) == 2 * i + 3 + assert f(3, i) == 2 ** (i + 3) - 3 + + def test_calling(self): + f = compile_function(llvmsnippet.calling1, [int]) + assert f(10) == 1 + + def test_call_default_arguments(self): + #py.test.skip("Method mapping not implemented") + f = compile_function(llvmsnippet.call_default_arguments, [int, int]) + for i in range(3): + assert f(i + 3, i) == llvmsnippet.call_default_arguments(i + 3, i) + + def DONTtest_call_list_default_argument(self): #issue we restart every test with a fresh set of globals + f = compile_function(llvmsnippet.call_list_default_argument, [int]) + for i in range(20): + assert f(i) == llvmsnippet.call_list_default_argument(i) + + def test_shift(self): + shl = compile_function(llvmsnippet.shiftleft, [int, int]) + shr = compile_function(llvmsnippet.shiftright, [int, int]) + assert shl(42,2) == llvmsnippet.shiftleft(42, 2) + assert shr(42,2) == llvmsnippet.shiftright(42,2) + +class TestFloat(object): + def test_float_f1(self): + f = compile_function(llvmsnippet.float_f1, [float]) + assert f(1.0) == 2.2 + + def test_float_int_bool(self): + f = compile_function(llvmsnippet.float_int_bool, [float]) + assert f(3.0) == 9.0 + + +class TestString(object): + def test_f2(self): + #py.test.skip("Method mapping not implemented") + f = compile_function(llvmsnippet.string_f2, [int, int]) + assert f(1, 0) == "a" + + +class TestPBC(object): + #py.test.skip("pbc not implemented") + def test_pbc_function1(self): + #py.test.skip("Method mapping not implemented") + f = compile_function(llvmsnippet.pbc_function1, [int]) + assert f(0) == 2 + assert f(1) == 4 + assert f(2) == 6 + assert f(3) == 8 + + def test_pbc_function2(self): + #py.test.skip("issue 'null' for Ptr's? or recurse into Ptr.TO?) see: opwriter.py") + #py.test.skip("Method mapping not implemented") + f = compile_function(llvmsnippet.pbc_function2, [int]) + assert f(0) == 13 + assert f(1) == 15 + assert f(2) == 17 + assert f(3) == 19 Added: pypy/dist/pypy/translator/js2/test/test_jseval.py ============================================================================== --- (empty file) +++ pypy/dist/pypy/translator/js2/test/test_jseval.py Mon May 29 19:45:52 2006 @@ -0,0 +1,57 @@ +from __future__ import division +import py + +from pypy.translator.js2.test.runtest import compile_function +from pypy.rpython.lltypesystem import lltype +from pypy.rpython.rjs import jseval +from pypy.translator.js import conftest + +def jsnative(cmd): + def do(): + return jseval(cmd) + return do + +getDate = jsnative("new Date().getDate()") +getTime = jsnative("Math.floor(new Date().getTime())") + +# +def test_jseval1(): + def jseval1(s): + return jseval(s) + + jseval1_fn = compile_function(jseval1, [str]) + e = "4+7" + assert jseval1_fn(e) == eval(e) + +def test_jsnative1(): + from time import localtime + + def jsnative1(): + getTime() + return getDate() + + jsnative1_fn = compile_function(jsnative1, []) + assert jsnative1_fn() == localtime()[2] + +callbacks = [] +n_times_called = lltype.malloc(lltype.GcArray(lltype.Signed), 1) + +def callback_function(): + n_times_called[0] += 1 + jseval("document.title=" + str(n_times_called[0])) + jseval("setTimeout('callback_function()', 100)") + +def test_register_callback(): + if not conftest.option.jsbrowser: + py.test.skip("works only in a browser (use py.test --browser)") + + def register_callback(): + callback_function() #..start timer + start_time = current_time = int(getTime()) + while current_time - start_time < 1000: + current_time = int(getTime()) + return n_times_called[0] + + register_callback_fn = compile_function(register_callback, []) + result = register_callback_fn() + assert result == 1 Added: pypy/dist/pypy/translator/js2/test/test_loops.py ============================================================================== --- (empty file) +++ pypy/dist/pypy/translator/js2/test/test_loops.py Mon May 29 19:45:52 2006 @@ -0,0 +1,66 @@ +import py + +from pypy.translator.js2.test.runtest import compile_function + +import sys + +def test_if_simple(): + def f(x): + if x == 1: + return 1 + else: + return 2 + fn = compile_function(f,[int]) + assert fn(1) == f(1) + assert fn(2) == f(2) + +def test_if_call(): + def check(x): + if x == 1: + return True + return False + + def f(x): + if check(x): + return 1 + else: + return 2 + + fn = compile_function(f,[int]) + assert fn(1) == f(1) + assert fn(2) == f(2) + +def test_while(): + def f(s): + while s > 1: + s -= 1 + return s + + fn = compile_function(f,[int]) + assert fn(38) == f(38) + assert fn(5) == f(5) + +def test_while_break(): + def f(s): + while s > 1: + if s == 8: + break + s -= 1 + return s + + fn = compile_function(f,[int]) + assert fn(38) == f(38) + assert fn(5) == f(5) + +def test_while_if(): + def f(x): + while x > 1: + if x%2 == 0: + x -= 7 + else: + x -= 3 + return x + + fn = compile_function(f,[int]) + assert fn(38) == f(38) + assert fn(5) == f(5) Added: pypy/dist/pypy/translator/js2/test/test_seq.py ============================================================================== --- (empty file) +++ pypy/dist/pypy/translator/js2/test/test_seq.py Mon May 29 19:45:52 2006 @@ -0,0 +1,110 @@ +from __future__ import division +import py + +from pypy.objspace.flow.model import Constant, Variable +from pypy.translator.js.test.runtest import compile_function +from pypy.translator.llvm.test import llvmsnippet + +class TestLLVMArray(object): + def test_array(self): + f = compile_function(llvmsnippet.array_simple, []) + assert f() == 42 + + def test_array1(self): + f = compile_function(llvmsnippet.array_simple1, [int]) + assert f(1) == 10 + assert f(-42) == -420 + + def test_array_setitem(self): + f = compile_function(llvmsnippet.array_setitem, [int]) + assert f(1) == 12 + assert f(2) == 13 + assert f(3) == 3 + + def test_array_add(self): + f = compile_function(llvmsnippet.array_add, [int, int, int, int, int]) + assert f(1,2,3,4,0) == 1 + assert f(1,2,3,4,1) == 2 + assert f(1,2,3,4,2) == 3 + assert f(1,2,5,6,3) == 6 + + def test_array_double(self): + f = compile_function(llvmsnippet.double_array, []) + assert f() == 15 + + def test_bool_array(self): + f = compile_function(llvmsnippet.bool_array, []) + assert f() == 1 + + def test_array_arg(self): + f = compile_function(llvmsnippet.array_arg, [int]) + assert f(5) == 0 + + def test_array_len(self): + f = compile_function(llvmsnippet.array_len, []) + assert f() == 10 + + def test_array_append(self): + f = compile_function(llvmsnippet.array_append, [int]) + for i in range(3): + assert f(i) == 0 + assert f(3) == 10 + + def test_array_reverse(self): + f = compile_function(llvmsnippet.array_reverse, [int]) + assert f(0) == 1 + assert f(1) == 0 + + def test_range(self): + f = compile_function(llvmsnippet.rangetest, [int]) + for i in range(10): + assert f(i) == i + + def test_array_pop(self): + f = compile_function(llvmsnippet.array_pop, [int]) + assert f(0) == 6 + assert f(1) == 7 + assert f(2) == 8 + + def test_newlist_zero_arg(self): + f = compile_function(llvmsnippet.newlist_zero_arg, [int]) + assert f(10) == 11 + assert f(-41) == -40 + + def test_big_array(self): + f = compile_function(llvmsnippet.big_array, [int]) + for i in range(18): + assert f(i) == i + + def DONTtest_access_global_array(self): #issue we restart every test with a fresh set of globals + f = compile_function(llvmsnippet.access_global_array, [int, int, int]) + for i in range(5): + for j in range(5): + assert f(i, j, i + j) == i + for i in range(5): + for j in range(5): + assert f(i, j, 0) == i + j + + def test_circular_list(self): + f = compile_function(llvmsnippet.circular_list, [int]) + assert f(0) == 0 + assert f(1) == 1 + assert f(10) == 1 + + +class TestTuple(object): + def test_f1(self): + f = compile_function(llvmsnippet.tuple_f1, [int]) + assert f(10) == 10 + assert f(15) == 15 + + def test_f3(self): + f = compile_function(llvmsnippet.tuple_f3, [int]) + assert f(10) == 10 + assert f(15) == 15 + assert f(30) == 30 + + def test_constant_tuple(self): + f = compile_function(llvmsnippet.constant_tuple, [int]) + for i in range(3, 7): + assert f(i) == i + 3 Added: pypy/dist/pypy/translator/js2/test/test_snippet.py ============================================================================== --- (empty file) +++ pypy/dist/pypy/translator/js2/test/test_snippet.py Mon May 29 19:45:52 2006 @@ -0,0 +1,94 @@ +from __future__ import division + +from pypy.translator.js2.test.runtest import compile_function +from pypy.translator.test import snippet as test + +import py + +class TestSnippet(object): + def test_if_then_else(self): + f = compile_function(test.if_then_else, [int, int, int]) + assert f(0, 12, 13) == 13 + assert f(13, 12, 13) == 12 + + def test_my_gcd(self): + f = compile_function(test.my_gcd, [int, int]) + assert f(15, 5) == 5 + assert f(18, 42) == 6 + + def test_is_perfect_number(self): + f = compile_function(test.is_perfect_number, [int]) + assert f(28) == 1 + assert f(123) == 0 + assert f(496) == 1 + + def test_my_bool(self): + f = compile_function(test.my_bool, [int]) + assert f(10) == 1 + assert f(1) == 1 + assert f(0) == 0 + + def test_two_plus_two(self): + f = compile_function(test.two_plus_two, []) + assert f() == 4 + + def test_sieve_of_eratosthenes(self): + py.test.skip("Loop error in loop detection software") + f = compile_function(test.sieve_of_eratosthenes, []) + assert f() == 1028 + + def test_nested_whiles(self): + py.test.skip("Loop error in loop detection software") + f = compile_function(test.nested_whiles, [int, int]) + assert test.nested_whiles(3,2) == f(3,2) + + def test_simple_func(self): + f = compile_function(test.simple_func, [int]) + assert f(1027) == 1028 + + def test_while_func(self): + while_func = compile_function(test.while_func, [int]) + assert while_func(10) == 55 + + def test_time_waster(self): + py.test.skip("Loop error in loop detection software") + f = compile_function(test.time_waster, [int]) + assert f(1) == 1 + assert f(2) == 2 + assert f(3) == 6 + assert f(4) == 12 + + def test_int_id(self): + f = compile_function(test.int_id, [int]) + assert f(1027) == 1027 + + def test_factorial2(self): + py.test.skip("unknown error") + factorial2 = compile_function(test.factorial2, [int]) + assert factorial2(5) == 120 + + def test_factorial(self): + py.test.skip("unknown error") + factorial = compile_function(test.factorial, [int]) + assert factorial(5) == 120 + + def test_set_attr(self): + set_attr = compile_function(test.set_attr, []) + assert set_attr() == 2 + + def test_merge_setattr(self): + merge_setattr = compile_function(test.merge_setattr, [bool]) + assert merge_setattr(1) == 1 + + def test_simple_method(self): + simple_method = compile_function(test.simple_method, [int]) + assert simple_method(65) == 65 + + def test_with_init(self): + with_init = compile_function(test.with_init, [int]) + assert with_init(42) == 42 + + def test_with_more_init(self): + with_more_init = compile_function(test.with_more_init, [int, bool]) + assert with_more_init(42, True) == 42 + assert with_more_init(42, False) == -42 Added: pypy/dist/pypy/translator/js2/test/test_typed.py ============================================================================== --- (empty file) +++ pypy/dist/pypy/translator/js2/test/test_typed.py Mon May 29 19:45:52 2006 @@ -0,0 +1,328 @@ +import sys +import py +from py.test import raises +from pypy.translator.test import snippet +from pypy.rpython.rarithmetic import r_uint, ovfcheck, ovfcheck_lshift + +from pypy.translator.js2.test.runtest import compile_function + +def test_call_five(): + def wrapper(): + lst = snippet.call_five() + res = list((len(lst), lst[0])) + expected = [1, 5] + return res == expected + fn = compile_function(wrapper, []) + result = fn() + assert result + +def test_get_set_del_slice(): + def get_set_del_nonneg_slice(): # no neg slices for now! + l = [ord('a'), ord('b'), ord('c'), ord('d'), ord('e'), ord('f'), ord('g'), ord('h'), ord('i'), ord('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 list((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])) + + def wrapper(): + res = get_set_del_nonneg_slice() + expected = [6, 3, ord('c'), 8, 11, ord('h'), 9, + 2, 3, ord('c'), + 1, 9, + 2, 11, ord('h')] + + return res == expected + + fn = compile_function(wrapper, []) + result = fn() + assert result + +def test_is(): + def testfn(): + l1 = [] + return l1 is l1 + fn = compile_function(testfn, []) + result = fn() + assert result == True + def testfn(): + l1 = [] + return l1 is None + fn = compile_function(testfn, []) + result = fn() + assert result == False + +def test_nones(): + a = [None] * 4 + def nones(): + a.append(None) + return len(a) + fn = compile_function(nones, []) + result = fn() + assert result == 4 + +def test_str_compare(): + def testfn_eq(i, j): + s1 = ['one', 'two'] + s2 = ['one', 'two', 'o', 'on', 'twos', 'foobar'] + return s1[i] == s2[j] + fn = compile_function(testfn_eq, [int, int]) + for i in range(2): + for j in range(6): + res = fn(i, j) + assert res == testfn_eq(i, j) + + def testfn_ne(i, j): + s1 = ['one', 'two'] + s2 = ['one', 'two', 'o', 'on', 'twos', 'foobar'] + return s1[i] != s2[j] + fn = compile_function(testfn_ne, [int, int]) + for i in range(2): + for j in range(6): + res = fn(i, j) + assert res == testfn_ne(i, j) + + def testfn_lt(i, j): + s1 = ['one', 'two'] + s2 = ['one', 'two', 'o', 'on', 'twos', 'foobar'] + return s1[i] < s2[j] + fn = compile_function(testfn_lt, [int, int]) + for i in range(2): + for j in range(6): + res = fn(i, j) + assert res == testfn_lt(i, j) + + def testfn_le(i, j): + s1 = ['one', 'two'] + s2 = ['one', 'two', 'o', 'on', 'twos', 'foobar'] + return s1[i] <= s2[j] + fn = compile_function(testfn_le, [int, int]) + for i in range(2): + for j in range(6): + res = fn(i, j) + assert res == testfn_le(i, j) + + def testfn_gt(i, j): + s1 = ['one', 'two'] + s2 = ['one', 'two', 'o', 'on', 'twos', 'foobar'] + return s1[i] > s2[j] + fn = compile_function(testfn_gt, [int, int]) + for i in range(2): + for j in range(6): + res = fn(i, j) + assert res == testfn_gt(i, j) + + def testfn_ge(i, j): + s1 = ['one', 'two'] + s2 = ['one', 'two', 'o', 'on', 'twos', 'foobar'] + return s1[i] >= s2[j] + fn = compile_function(testfn_ge, [int, int]) + for i in range(2): + for j in range(6): + res = fn(i, j) + assert res == testfn_ge(i, j) + +def test_str_methods(): + def testfn_startswith(i, j): + s1 = ['one', 'two'] + s2 = ['one', 'two', 'o', 'on', 'ne', 'e', 'twos', 'foobar', 'fortytwo'] + return s1[i].startswith(s2[j]) + fn = compile_function(testfn_startswith, [int, int]) + for i in range(2): + for j in range(9): + res = fn(i, j) + assert res == testfn_startswith(i, j) + + def testfn_endswith(i, j): + s1 = ['one', 'two'] + s2 = ['one', 'two', 'o', 'on', 'ne', 'e', 'twos', 'foobar', 'fortytwo'] + return s1[i].endswith(s2[j]) + fn = compile_function(testfn_endswith, [int, int]) + for i in range(2): + for j in range(9): + res = fn(i, j) + assert res == testfn_endswith(i, j) + +def test_str_join(): + #py.test.skip("issue with malloc_varsize of varsized struct (rpystring here)") + py.test.skip("stringBuilder support") + def testfn(i, j): + s1 = [ '', ',', ' and '] + s2 = [ [], ['foo'], ['bar', 'baz', 'bazz']] + return len(s1[i].join(s2[j])) + + fn = compile_function(testfn, [int, int]) + for i in range(3): + for j in range(3): + res = fn(i, j) + assert res == testfn(i, j) + +def test_unichr_eq(): + l = list(u'Hello world') + def f(i, j): + return l[i] == l[j] + fn = compile_function(f, [int, int]) + for i in range(len(l)): + for j in range(len(l)): + res = fn(i, j) + assert res == f(i,j) + +def test_unichr_ne(): + l = list(u'Hello world') + def f(i, j): + return l[i] != l[j] + fn = compile_function(f, [int, int]) + 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(): + py.test.skip("ord semantics") + l = list(u'Hello world') + def f(i): + return ord(l[i]) + fn = compile_function(f, [int]) + for i in range(len(l)): + res = fn(i) + assert res == f(i) + +def test_unichr_unichr(): + py.test.skip("unichr function") + l = list(u'Hello world') + def f(i, j): + return l[i] == unichr(j) + fn = compile_function(f, [int, int]) + 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])) + +# floats +def test_float_operations(): + py.test.skip("issue with ll_math_fmod calling itself") + import math + def func(x, y): + z = x + y / 2.1 * x + z = math.fmod(z, 60.0) + z = pow(z, 2) + z = -z + return int(z) + + fn = compile_function(func, [float, float]) + r1 = fn(5.0, 6.0) + r2 = func(5.0, 6.0) + assert r1 == r2-1 #-1 for stupid spidermonkey rounding error + +def test_rpbc_bound_method_static_call(): + class R: + def meth(self): + return 0 + r = R() + m = r.meth + def fn(): + return m() + res = compile_function(fn, [])() + assert res == 0 + +def test_constant_return_disagreement(): + class R: + def meth(self): + return 0 + r = R() + def fn(): + return r.meth() + res = compile_function(fn, [])() + assert res == 0 + +def test_stringformatting(): + py.test.skip("StringBuilder not implemented") + def fn(i): + return "you said %d, you did" % i + def wrapper(i): + res = fn(i) + return res == "you said 42, you did" + + f = compile_function(wrapper, [int]) + assert f(42) + +def test_str2int(): + def fn(i): + return str(i) + def wrapper(i): + res = fn(i) + return res == "42" + + f = compile_function(wrapper, [int]) + assert f(42) + +def test_int_invert(): + def fn(i): + return ~i + f = compile_function(fn, [int]) + for i in range(-15, 15): + assert f(i) == fn(i) + +def DONTtest_uint_invert(): #issue with Javascript Number() having a larger range + def fn(i): + inverted = ~i + inverted -= sys.maxint + return inverted + f = compile_function(fn, [r_uint]) + for value in range(1, 15): + i = r_uint(value) + assert str(f(i)) == str(fn(i)) + s = 0xfffffff + for value in range(s, s+1024, 64): + i = r_uint(value) + assert str(f(i)) == str(fn(i)) + +def test_int_abs(): + def int_abs_(n): + return abs(n) + f = compile_function(int_abs_, [int]) + for i in (-25, 0, 75): + assert f(i) == int_abs_(i) + +def test_float_abs(): + def float_abs_(n): + return abs(n) + f = compile_function(float_abs_, [float]) + for i in (-100.1 -50.2, -0.0, 0.0, 25.3, 50.4): + assert f(i) == float_abs_(i) + +def test_cast_to_int(): + def casting(v): + return int(ord(chr(v))) + f = compile_function(casting, [int]) + for ii in range(255): + assert f(ii) == ii + +def test_char_comparisons(): + py.test.skip("chr/ord semantics") + def comps(v): + x = chr(v) + res = 0 + res += x < chr(0) + res += x > chr(1) + res += x >= chr(127) + res += x < chr(128) + res += x < chr(250) + return res + f = compile_function(comps, [int]) + for ii in range(255): + assert f(ii) == comps(ii) From fijal at codespeak.net Mon May 29 20:00:48 2006 From: fijal at codespeak.net (fijal at codespeak.net) Date: Mon, 29 May 2006 20:00:48 +0200 (CEST) Subject: [pypy-svn] r27875 - in pypy/dist/pypy/translator/js2: . jssrc Message-ID: <20060529180048.8372F10053@code0.codespeak.net> Author: fijal Date: Mon May 29 20:00:47 2006 New Revision: 27875 Added: pypy/dist/pypy/translator/js2/jssrc/ pypy/dist/pypy/translator/js2/jssrc/misc.js Modified: pypy/dist/pypy/translator/js2/js.py Log: Added missing javascript source file Modified: pypy/dist/pypy/translator/js2/js.py ============================================================================== --- pypy/dist/pypy/translator/js2/js.py (original) +++ pypy/dist/pypy/translator/js2/js.py Mon May 29 20:00:47 2006 @@ -48,7 +48,7 @@ self.filename = self.cli.tmpfile data = self.filename.open().read() - src_filename = _path_join(os.path.dirname(__file__), 'src', 'misc.js') + src_filename = _path_join(os.path.dirname(__file__), 'jssrc', 'misc.js') f = self.cli.tmpfile.open("w") s = open(src_filename).read() f.write(s) Added: pypy/dist/pypy/translator/js2/jssrc/misc.js ============================================================================== --- (empty file) +++ pypy/dist/pypy/translator/js2/jssrc/misc.js Mon May 29 20:00:47 2006 @@ -0,0 +1,72 @@ +var in_browser; +try { + dummy = alert; + in_browser = true; +} catch (e) { + in_browser = false; +} + +function log(s) { + if (in_browser) { + var logdiv = document.getElementById('logdiv'); + logdiv.innerHTML = new Date().getTime() + ': ' + s + "
" + logdiv.innerHTML; + } else { + print('log: ' + s); + } +} + +function alloc_and_set(L0, len, elem) { + l = []; + for(i = 0; i < len; ++i){ + l[i] = elem; + } + return(l); +} + +function strconcat(s1, s2) { + return(s1+s2); +} + +function stritem(cl, s, it) { + return(s[it]); +} + +function delitem(fn, l, i) { + for(j = i; j < l.length-1; ++j) { + l[j] = l[j+1]; + } + l.length--; +} + +function strcmp(s1, s2) { + if ( s1 < s2 ) { + return ( -1 ); + } else if ( s1 == s2 ) { + return ( 0 ); + } + return (1); +} + +function startswith(s1, s2) { + if (s1.lengths1.length) { + return(false); + } + for (i = s1.length-s2.length; i Author: fijal Date: Mon May 29 20:03:06 2006 New Revision: 27876 Modified: pypy/dist/pypy/translator/js2/test/test_genllvm1.py Log: Non-working import. Modified: pypy/dist/pypy/translator/js2/test/test_genllvm1.py ============================================================================== --- pypy/dist/pypy/translator/js2/test/test_genllvm1.py (original) +++ pypy/dist/pypy/translator/js2/test/test_genllvm1.py Mon May 29 20:03:06 2006 @@ -1,7 +1,6 @@ from __future__ import division import sys -import autopath import py from pypy.objspace.flow.model import Constant, Variable From arigo at codespeak.net Mon May 29 21:07:29 2006 From: arigo at codespeak.net (arigo at codespeak.net) Date: Mon, 29 May 2006 21:07:29 +0200 (CEST) Subject: [pypy-svn] r27879 - pypy/dist/lib-python Message-ID: <20060529190729.C3F1F10053@code0.codespeak.net> Author: arigo Date: Mon May 29 21:07:28 2006 New Revision: 27879 Modified: pypy/dist/lib-python/conftest.py Log: Adding _weakref to a few tests that reply on them. Modified: pypy/dist/lib-python/conftest.py ============================================================================== --- pypy/dist/lib-python/conftest.py (original) +++ pypy/dist/lib-python/conftest.py Mon May 29 21:07:28 2006 @@ -468,7 +468,7 @@ RegrTest('test_decimal.py', enabled=True), RegrTest('test_decorators.py', enabled=True, core=True), RegrTest('test_deque.py', enabled=True, core=True), - RegrTest('test_descr.py', enabled=True, core=True, oldstyle=True), + RegrTest('test_descr.py', enabled=True, core=True, oldstyle=True, usemodules='_weakref'), RegrTest('test_descrtut.py', enabled=True, core=True, oldstyle=True), RegrTest('test_dict.py', enabled=True, core=True), @@ -506,7 +506,7 @@ RegrTest('test_future1.py', enabled=True, dumbtest=1, core=True), RegrTest('test_future2.py', enabled=True, dumbtest=1, core=True), RegrTest('test_future3.py', enabled=True, core=True), - RegrTest('test_gc.py', enabled=True, dumbtest=1), + RegrTest('test_gc.py', enabled=True, dumbtest=1, usemodules='_weakref'), RegrTest('test_gdbm.py', enabled=False, dumbtest=1), RegrTest('test_generators.py', enabled=True, core=True), #rev 10840: 30 of 152 tests fail @@ -664,7 +664,7 @@ RegrTest('test_site.py', enabled=False, core=False), # considered cpython impl-detail # Needs non-faked codecs. RegrTest('test_slice.py', enabled=True, dumbtest=1, core=True), - RegrTest('test_socket.py', enabled=False, usemodules='thread'), + RegrTest('test_socket.py', enabled=False, usemodules='thread _weakref'), RegrTest('test_socket_ssl.py', enabled=False), RegrTest('test_socketserver.py', enabled=False, usemodules='thread'), @@ -752,8 +752,7 @@ RegrTest('test_warnings.py', enabled=True, core=True), RegrTest('test_wave.py', enabled=False, dumbtest=1), - RegrTest('test_weakref.py', enabled=True, core=True), - #rev 10840: ImportError: _weakref + RegrTest('test_weakref.py', enabled=True, core=True, usemodules='_weakref'), RegrTest('test_whichdb.py', enabled=True), RegrTest('test_winreg.py', enabled=False), From fijal at codespeak.net Tue May 30 10:11:51 2006 From: fijal at codespeak.net (fijal at codespeak.net) Date: Tue, 30 May 2006 10:11:51 +0200 (CEST) Subject: [pypy-svn] r27891 - pypy/dist/pypy/translator/js2/jssrc Message-ID: <20060530081151.E0F5E10057@code0.codespeak.net> Author: fijal Date: Tue May 30 10:11:39 2006 New Revision: 27891 Modified: pypy/dist/pypy/translator/js2/jssrc/misc.js Log: Syntactic sugar for inheritance. Modified: pypy/dist/pypy/translator/js2/jssrc/misc.js ============================================================================== --- pypy/dist/pypy/translator/js2/jssrc/misc.js (original) +++ pypy/dist/pypy/translator/js2/jssrc/misc.js Tue May 30 10:11:39 2006 @@ -1,19 +1,39 @@ -var in_browser; -try { - dummy = alert; - in_browser = true; -} catch (e) { - in_browser = false; -} - -function log(s) { - if (in_browser) { - var logdiv = document.getElementById('logdiv'); - logdiv.innerHTML = new Date().getTime() + ': ' + s + "
" + logdiv.innerHTML; - } else { - print('log: ' + s); +Function.prototype.method = function (name, func) { + this.prototype[name] = func; + return this; +}; + +Function.method('inherits', function (parent) { + var d = 0, p = (this.prototype = new parent()); + this.method('uber', function uber(name) { + var f, r, t = d, v = parent.prototype; + if (t) { + while (t) { + v = v.constructor.prototype; + t -= 1; + } + f = v[name]; + } else { + f = p[name]; + if (f == this[name]) { + f = v[name]; + } + } + d += 1; + r = f.apply(this, Array.prototype.slice.apply(arguments, [1])); + d -= 1; + return r; + }); + return this; +}); + +Function.method('swiss', function (parent) { + for (var i = 1; i < arguments.length; i += 1) { + var name = arguments[i]; + this.prototype[name] = parent.prototype[name]; } -} + return this; +}); function alloc_and_set(L0, len, elem) { l = []; From hpk at codespeak.net Tue May 30 11:15:36 2006 From: hpk at codespeak.net (hpk at codespeak.net) Date: Tue, 30 May 2006 11:15:36 +0200 (CEST) Subject: [pypy-svn] r27896 - pypy/extradoc/talk/ep2006 Message-ID: <20060530091536.173CC10063@code0.codespeak.net> Author: hpk Date: Tue May 30 11:15:34 2006 New Revision: 27896 Modified: pypy/extradoc/talk/ep2006/planning.txt Log: allocation of people for the EP2006 talks that michael and me suggest. Modified: pypy/extradoc/talk/ep2006/planning.txt ============================================================================== --- pypy/extradoc/talk/ep2006/planning.txt (original) +++ pypy/extradoc/talk/ep2006/planning.txt Tue May 30 11:15:34 2006 @@ -4,12 +4,17 @@ 1. an introductory talk, probably based on michael's talk from the accu conference (but likely a bit shorter) + Michael Hudson 2. a "what pypy can do for you" talk, covering the ext-compiler, stackless, etc. + + Armin Rigo, Carl Friedrich Bolz 3. an architecture session, similar to that held at pycon this year. + Samuele Pedroni, Holger Krekel 4. a talk on the methodology side of the project. + Bea During In addition Eric will probably give a lightning talk about the JS backend. From pedronis at codespeak.net Tue May 30 11:16:04 2006 From: pedronis at codespeak.net (pedronis at codespeak.net) Date: Tue, 30 May 2006 11:16:04 +0200 (CEST) Subject: [pypy-svn] r27897 - pypy/extradoc/talk/dls2006 Message-ID: <20060530091604.A3A3710057@code0.codespeak.net> Author: pedronis Date: Tue May 30 11:16:02 2006 New Revision: 27897 Modified: pypy/extradoc/talk/dls2006/draft.txt Log: some XXX comments Modified: pypy/extradoc/talk/dls2006/draft.txt ============================================================================== --- pypy/extradoc/talk/dls2006/draft.txt (original) +++ pypy/extradoc/talk/dls2006/draft.txt Tue May 30 11:16:02 2006 @@ -418,7 +418,8 @@ We mitigate the potential efficiency problem by wise choices and compromises for the domain used; the foremost example of this is that our RPython type inference performs almost no automatic specialization -of functions. We achieved enough precision for our purpose, though. +of functions XXX class annotation vs concrete runtime class setsXXX. +We achieved enough precision for our purpose, though. In the sequel, we give a more precise description of this process and justify our claim that good performance and enough precision can be @@ -479,7 +480,7 @@ Standard Object Space, form the full Python interpreter of PyPy. It is an RPython program, and the whole purpose of the translation process is to accept this as *input*, and translate it to an efficient form. Its -architecture is not relevant to the way it is translated. +architecture is not relevant to the way it is translated. XXX? However, the bytecode interpreter plays a double role, at two different levels. The so-called Object Spaces are *domains* in the abstract @@ -537,7 +538,8 @@ .. [#] This is useful at this level for some constructs of the bytecode interpreter, which can temporarily wrap internal values and push them onto the regular value stack among the other application-level objects. - We need to be able to unwrap them again later. + We need to be able to unwrap them again later. XXX compile-time + computation in the helpers In the flow graph, branching occurs when the bytecode interpreter tries to inspect the truth value of placeholder objects, as it would in @@ -786,7 +788,7 @@ :latexformula:`$Inst(MyClass)$` within the positive branch of the ``if``. (Remember that our graphs are in SSI form, which means that the ``x`` inside each basic block is a different Variable with a possibly -different type as annotation.) +different type as annotation.) XXX flow sensivity and SSA This is implemented by introducing an extended family of types for boolean values: @@ -809,7 +811,7 @@ With the help of the above technique, we achieve a reasonable precision in small examples. For larger examples, a different, non-local -technique is required: the specialization of functions. +technique is required: the specialization of functions. XXX use 'polymorphism' As described in the introduction, the most important downside of our approach is that automatic specialization is a potential From hpk at codespeak.net Tue May 30 11:19:52 2006 From: hpk at codespeak.net (hpk at codespeak.net) Date: Tue, 30 May 2006 11:19:52 +0200 (CEST) Subject: [pypy-svn] r27898 - pypy/extradoc/talk/ep2006 Message-ID: <20060530091952.6E7DE10057@code0.codespeak.net> Author: hpk Date: Tue May 30 11:19:49 2006 New Revision: 27898 Added: pypy/extradoc/talk/ep2006/archsession.txt Log: reuse and modified the pycon2006 talk (archsession) for EP2006, updating it a bit. Added: pypy/extradoc/talk/ep2006/archsession.txt ============================================================================== --- (empty file) +++ pypy/extradoc/talk/ep2006/archsession.txt Tue May 30 11:19:49 2006 @@ -0,0 +1,45 @@ +Author Names +------------ + +Samuele Pedroni, Holger Krekel + +Contact Information +------------------- + +pypy-dev at codespeak.net (developer mailing list) +pedronis at strakt.com +hpk at merlinux.de + +Requested Timeslot +------------------ + +30 minutes (or longer). + +Summary of proposed presentation +-------------------------------- + +XXX DRAFT + +In this session we will present and interactively discuss with +the audience the basic architectural pictures of PyPy - a next +generation Python compiler and interpreter. We'd are going to +emphasize the various emerging possibilities for further +development part of which will be an ongoing effort of the +European Union's funded part of the PyPy project. We also + +In particular, we'll describe the following architectural pictures +and point out extension and optimization possibilities: + +- Language Implementation: Bytecode Interpreter and Object Space interaction +- Translation to low level languages (C/LLVM) +- Translation to higher level languages (e.g. Squeak/Java/.NET) +- JIT-compiler architecture (very-low-level/l3 interpreter) +- Interweaving of Garbage Collection, threading and stackless + operations into the translation process + +Intended audience +----------------- + +Python programmers and people interested in the general picture +of the PyPy code base. + From fijal at codespeak.net Tue May 30 11:23:43 2006 From: fijal at codespeak.net (fijal at codespeak.net) Date: Tue, 30 May 2006 11:23:43 +0200 (CEST) Subject: [pypy-svn] r27899 - in pypy/dist/pypy/translator/js2: . test Message-ID: <20060530092343.F193D1005A@code0.codespeak.net> Author: fijal Date: Tue May 30 11:23:03 2006 New Revision: 27899 Modified: pypy/dist/pypy/translator/js2/_class.py pypy/dist/pypy/translator/js2/asmgen.py pypy/dist/pypy/translator/js2/database.py pypy/dist/pypy/translator/js2/function.py pypy/dist/pypy/translator/js2/js.py pypy/dist/pypy/translator/js2/opcodes.py pypy/dist/pypy/translator/js2/test/test_class.py Log: Added inheritance. Modified: pypy/dist/pypy/translator/js2/_class.py ============================================================================== --- pypy/dist/pypy/translator/js2/_class.py (original) +++ pypy/dist/pypy/translator/js2/_class.py Tue May 30 11:23:03 2006 @@ -13,13 +13,19 @@ self.name = classdef._name.split('.')[-1] if not self.is_root(classdef): - self.db.pending_class(classdef._superclass) + self.parent = self.db.pending_class(classdef._superclass) + self.order = self.parent.order + 1 + else: + self.order = 0 def __hash__(self): return hash(self.classdef) def __eq__(self, other): return self.classdef == other.classdef + + def __cmp__(self, other): + return cmp(self.order, other.order) def is_root(classdef): return classdef._superclass is None @@ -28,13 +34,6 @@ def get_name(self): return self.name - def get_base_class(self): - base_class = self.classdef._superclass - if self.is_root(base_class): - return '[mscorlib]System.Object' - else: - return base_class._name - def render(self, ilasm): if self.is_root(self.classdef): return @@ -52,16 +51,20 @@ #if cts_type != 'void': # ilasm.field(f_name, cts_type) - # TODO: should the .ctor set the default values? - #self._ctor() - - # lazy import to avoid circular dependencies - #import pypy.translator.cli.function as function + if not self.is_root(self.classdef): + basename = self.basename(self.classdef._superclass._name) + if basename != 'Root': + ilasm.inherits(self.name, basename) + for m_name, m_meth in self.classdef._methods.iteritems(): f = self.db.function_class(self.db, m_meth.graph, m_name, is_method = True, _class = self.name) f.render(ilasm) - + + self.db.record_class(self.classdef, self.name) + + def basename(self, name): + return name.split('.')[-1] #def _ctor(self): # self.ilasm.begin_function('.ctor', [], 'void', False, 'specialname', 'rtspecialname', 'instance') Modified: pypy/dist/pypy/translator/js2/asmgen.py ============================================================================== --- pypy/dist/pypy/translator/js2/asmgen.py (original) +++ pypy/dist/pypy/translator/js2/asmgen.py Tue May 30 11:23:03 2006 @@ -224,5 +224,8 @@ def end_try(self): self.codegenerator.closeblock() + def inherits(self, subclass_name, parent_name): + self.codegenerator.writeline("%s.inherits(%s);"%(subclass_name, parent_name)) + #def finish ( self ): # self . outfile . write ( "%r" % self . right_hand ) Modified: pypy/dist/pypy/translator/js2/database.py ============================================================================== --- pypy/dist/pypy/translator/js2/database.py (original) +++ pypy/dist/pypy/translator/js2/database.py Tue May 30 11:23:03 2006 @@ -50,7 +50,9 @@ self.pending_node(self.function_class(self, graph)) def pending_class(self, classdef): - self.pending_node(Class(self, classdef)) + c = Class(self, classdef) + self.pending_node(c) + return c def pending_record(self, record): r = Record(self, record) Modified: pypy/dist/pypy/translator/js2/function.py ============================================================================== --- pypy/dist/pypy/translator/js2/function.py (original) +++ pypy/dist/pypy/translator/js2/function.py Tue May 30 11:23:03 2006 @@ -16,7 +16,7 @@ from pypy.translator.js2.log import log -class LoopFinder: +class LoopFinder(object): def __init__(self, startblock): self.loops = {} @@ -60,6 +60,7 @@ self._class = _class self._set_args() self._set_locals() + self.order = 0 def get_name(self): return self.name @@ -69,6 +70,9 @@ def __eq__(self, other): return self.graph == other.graph + + def __cmp__(self, other): + return cmp(self.order, other.order) def _is_return_block(self, block): return (not block.exits) and len(block.inputargs) == 1 Modified: pypy/dist/pypy/translator/js2/js.py ============================================================================== --- pypy/dist/pypy/translator/js2/js.py (original) +++ pypy/dist/pypy/translator/js2/js.py Tue May 30 11:23:03 2006 @@ -25,18 +25,34 @@ from pypy.translator.cli.gencli import GenCli +from heapq import heappush, heappop + def _path_join(root_path, *paths): path = root_path for p in paths: path = os.path.join(path, p) return path -class JS(object): +class JS(GenCli): def __init__(self, translator, functions=[], stackless=False, compress=False, logging=False): - self.cli = GenCli(udir, translator, type_system_class = JTS, opcode_dict = opcodes,\ + GenCli.__init__(self, udir, translator, type_system_class = JTS, opcode_dict = opcodes,\ name_suffix = '.js', function_class = Function, database_class = LowLevelDatabase) self.translator = translator + def gen_pendings(self): + while self.db._pending_nodes: + node = self.db._pending_nodes.pop() + to_render = [] + nparent = node + while nparent.order != 0: + nparent = nparent.parent + to_render.append(nparent) + to_render.reverse() + for i in to_render: + i.render(self.ilasm) + + node.render(self.ilasm) + def write_source(self): # write down additional functions @@ -44,15 +60,16 @@ # not be used as inlined, rather another script to load # this is just workaround - self.cli.generate_source(AsmGen) - self.filename = self.cli.tmpfile + self.generate_source(AsmGen) - data = self.filename.open().read() + data = self.tmpfile.open().read() src_filename = _path_join(os.path.dirname(__file__), 'jssrc', 'misc.js') - f = self.cli.tmpfile.open("w") + f = self.tmpfile.open("w") s = open(src_filename).read() f.write(s) f.write(data) f.close() - return self.cli.tmpfile + self.filename = self.tmpfile + + return self.tmpfile Modified: pypy/dist/pypy/translator/js2/opcodes.py ============================================================================== --- pypy/dist/pypy/translator/js2/opcodes.py (original) +++ pypy/dist/pypy/translator/js2/opcodes.py Tue May 30 11:23:03 2006 @@ -213,8 +213,10 @@ 'oosetfield' : [SetField], 'oogetfield' : [GetField], 'oosend' : [CallMethod], - 'ooupcast' : [_NotImplemented("Inheritance not implemented (ooupcast)")], - 'oodowncast' : [_NotImplemented("Inheritance not implemented (oodowncast)")], + #'ooupcast' : [_NotImplemented("Inheritance not implemented (ooupcast)")], + #'oodowncast' : [_NotImplemented("Inheritance not implemented (oodowncast)")], + 'ooupcast' : DoNothing, + 'oodowncast' : DoNothing, 'oononnull' : [PushAllArgs,_Prefix('!!')], 'oostring' : [CastString], 'oois' : '==', # FIXME: JS does not have real equal Modified: pypy/dist/pypy/translator/js2/test/test_class.py ============================================================================== --- pypy/dist/pypy/translator/js2/test/test_class.py (original) +++ pypy/dist/pypy/translator/js2/test/test_class.py Tue May 30 11:23:03 2006 @@ -24,47 +24,45 @@ assert f(2) == 10 def test_inherit1(self): - py.test.skip("Inheritance not implemented") - #py.test.skip("issue 'null' for Ptr's? or recurse into Ptr.TO?) see: opwriter.py") f = compile_function(llvmsnippet.class_inherit1, []) assert f() == 11 def test_inherit2(self): - py.test.skip("Inheritance not implemented") + #py.test.skip("Inheritance not implemented") #py.test.skip("issue 'null' for Ptr's? or recurse into Ptr.TO?) see: opwriter.py") f = compile_function(llvmsnippet.class_inherit2, []) assert f() == 1 def test_method_of_base_class(self): - py.test.skip("Inheritance not implemented") + #py.test.skip("Inheritance not implemented") #py.test.skip("issue 'null' for Ptr's? or recurse into Ptr.TO?) see: opwriter.py") f = compile_function(llvmsnippet.method_of_base_class, []) assert f() == 14 def test_attribute_from_base_class(self): - py.test.skip("Inheritance not implemented") + #py.test.skip("Inheritance not implemented") f = compile_function(llvmsnippet.attribute_from_base_class, []) assert f() == 4 def test_direct_call_of_virtual_method(self): - py.test.skip("Inheritance not implemented") + #py.test.skip("Inheritance not implemented") #py.test.skip("issue 'null' for Ptr's? or recurse into Ptr.TO?) see: opwriter.py") f = compile_function(llvmsnippet.direct_call_of_virtual_method, []) assert f() == 14 def test_flow_type(self): - py.test.skip("Inheritance not implemented") + py.test.skip("isinstanceof not implemented") f = compile_function(llvmsnippet.flow_type, []) assert f() == 16 def test_merge_class(self): - py.test.skip("Inheritance not implemented") + #py.test.skip("Inheritance not implemented") f = compile_function(llvmsnippet.merge_classes, [bool]) assert f(True) == 1 assert f(False) == 2 def test_attribute_instance(self): - py.test.skip("Inheritance not implemented") + #py.test.skip("Inheritance not implemented") f = compile_function(llvmsnippet.attribute_instance, [bool]) assert f(True) == 1 assert f(False) == 2 @@ -83,12 +81,13 @@ assert f(15) == 25 def test_call_degrading_func(self): - py.test.skip("Inheritance not implemented") + py.test.skip("isinstanceof not implemented") f = compile_function(llvmsnippet.call_degrading_func, [bool]) assert f(True) == llvmsnippet.call_degrading_func(True) assert f(False) == llvmsnippet.call_degrading_func(False) def test_circular_classdef(self): - py.test.skip("Inheritance not implemented") + py.test.skip("Problems with constant names") + #py.test.skip("Inheritance not implemented") f = compile_function(llvmsnippet.circular_classdef, []) assert f() == 10 From arigo at codespeak.net Tue May 30 11:50:55 2006 From: arigo at codespeak.net (arigo at codespeak.net) Date: Tue, 30 May 2006 11:50:55 +0200 (CEST) Subject: [pypy-svn] r27900 - pypy/dist/pypy/rpython Message-ID: <20060530095055.C74B810057@code0.codespeak.net> Author: arigo Date: Tue May 30 11:50:54 2006 New Revision: 27900 Modified: pypy/dist/pypy/rpython/objectmodel.py Log: Fix for 2.5 compatibility. Modified: pypy/dist/pypy/rpython/objectmodel.py ============================================================================== --- pypy/dist/pypy/rpython/objectmodel.py (original) +++ pypy/dist/pypy/rpython/objectmodel.py Tue May 30 11:50:54 2006 @@ -39,7 +39,7 @@ def instantiate(cls): "Create an empty instance of 'cls'." if isinstance(cls, type): - return object.__new__(cls) + return cls.__new__(cls) else: return new.instance(cls) From nico at codespeak.net Tue May 30 12:27:16 2006 From: nico at codespeak.net (nico at codespeak.net) Date: Tue, 30 May 2006 12:27:16 +0200 (CEST) Subject: [pypy-svn] r27902 - pypy/extradoc/sprintinfo/europython-2006 Message-ID: <20060530102716.02A0C10036@code0.codespeak.net> Author: nico Date: Tue May 30 12:27:14 2006 New Revision: 27902 Added: pypy/extradoc/sprintinfo/europython-2006/ pypy/extradoc/sprintinfo/europython-2006/announce.txt pypy/extradoc/sprintinfo/europython-2006/people.txt Log: create almost empty europython-2006 sprintinfo Added: pypy/extradoc/sprintinfo/europython-2006/announce.txt ============================================================================== --- (empty file) +++ pypy/extradoc/sprintinfo/europython-2006/announce.txt Tue May 30 12:27:14 2006 @@ -0,0 +1,16 @@ +EuroPython PyPy sprint 6-9 July 2006 +==================================================== + +This sprint will be held right after the EuroPython conference in +Geneva at CERN, from the 6th to the 9th of July 2006. + +The main focus of the sprint is yet to be defined. + +If you'd like to come, please subscribe to the `pypy-sprint mailing list`_ +and drop a note about your interests and post any questions. More +organisational information will be send to that list. We'll keep +a list of `people`_ which we'll update (which you can do so yourself +if you have codespeak commit rights). + +.. _`pypy-sprint mailing list`: http://codespeak.net/mailman/listinfo/pypy-sprint +.. _`people`: http://codespeak.net/pypy/extradoc/sprintinfo/europython-2006/people.html Added: pypy/extradoc/sprintinfo/europython-2006/people.txt ============================================================================== --- (empty file) +++ pypy/extradoc/sprintinfo/europython-2006/people.txt Tue May 30 12:27:14 2006 @@ -0,0 +1,44 @@ +People coming to the EuroPython sprint July 2006 +================================================== + +People who have a ``?`` in their arrive/depart or accomodation +column are known to be coming but there are no details +available yet from them. + +==================== ============== ===================== + Name Arrive/Depart Accomodation +==================== ============== ===================== +==================== ============== ===================== + +People on the following list were present at previous sprints: + +==================== ============== ===================== + Name Arrive/Depart Accomodation +==================== ============== ===================== +Michael Hudson ? ? +Armin Rigo ? ? +Holger Krekel ? ? +Carl Friedrich Bolz ? ? +Eric van Riet Paap ? ? +Maciej Fijalkowski ? ? +Anders Chrigstroem ? ? +Samuele Pedroni ? ? +Christian Tismer ? ? +Antonio Cuni ? ? +Anders Lehmann ? ? +Niklaus Haldimann ? ? +Christian Tismer ? ? +Jacob Hallen ? ? +Aurelien Campeas ? ? +Alexandre Fayolle ? ? +Lene Wagner ? ? +Amaury Forgeot d'Arc ? ? +Valentino Volonghi ? ? +Boris Feigin ? ? +Andrew Thompson ? ? +Bert Freudenberg ? ? +Laura Creighton ? ? +Beatrice Duering ? ? +Richard Emslie ? ? +Johan Hahn ? ? +==================== ============== ===================== From nico at codespeak.net Tue May 30 12:29:03 2006 From: nico at codespeak.net (nico at codespeak.net) Date: Tue, 30 May 2006 12:29:03 +0200 (CEST) Subject: [pypy-svn] r27903 - pypy/dist/pypy/doc Message-ID: <20060530102903.4F82810057@code0.codespeak.net> Author: nico Date: Tue May 30 12:29:01 2006 New Revision: 27903 Modified: pypy/dist/pypy/doc/events.txt pypy/dist/pypy/doc/news.txt Log: * move old items from upcoming events to (old) news * add announce for EuroPython sprint * add news for summer of code and agile conferences Modified: pypy/dist/pypy/doc/events.txt ============================================================================== --- pypy/dist/pypy/doc/events.txt (original) +++ pypy/dist/pypy/doc/events.txt Tue May 30 12:29:01 2006 @@ -7,25 +7,42 @@ .. _`over there`: webcal://pypycal.sabi.net///calendars/PyPy.ics -Talks at Python UK/ACCU Conference (United Kingdom) -=================================================================== +Duesseldorf PyPy sprint 2-9 June 2006 +================================================================== -*April 19th - April 22nd 2006.* Read more at the `ACCU site`_. +The next PyPy sprint will be held in the Computer Science department of +Heinrich-Heine Universitaet Duesseldorf from the *2nd to the 9th of June*. +Main focus of the sprint will be on the goals of the upcoming June 0.9 +release. -.. _`ACCU site`: http://www.accu.org/ +Read more in `the sprint announcement`_, see who is planning to attend +on the `people page`_. -Sprint in Tokyo (Japan) -=================================================================== +.. _`the sprint announcement`: http://codespeak.net/pypy/extradoc/sprintinfo/ddorf2006/announce.html +.. _`people page`: http://codespeak.net/pypy/extradoc/sprintinfo/ddorf2006/people.html -*April 23rd - April 29th 2006.* -The sprint will be Akihabara, Tokyo, Japan. Our hosts are -FSIJ (Free Software Initiative of Japan) and out aim for the sprint -will be to promote Python and introduce people to PyPy. +PyPy at XP 2006 and Agile 2006 +================================================================== -Read more in `the announcement`_, see who is planning to attend -on the `people page`_. +PyPy will present experience reports at the two main agile conferences +this year, `XP 2006`_ and `Agile 2006`_. +Both experience reports focus on aspects of the sprint-driven +development method that is being used in PyPy. + +.. _`XP 2006`: http://virtual.vtt.fi/virtual/xp2006/ +.. _`Agile 2006`: http://www.agile2006.org/ + + +EuroPython PyPy sprint 6-9 July 2006 +================================================================== + +Once again a PyPy sprint will take place right after the EuroPython +Conference. This year it will be from the *6th to the 9th of July*. -.. _`the announcement`: http://codespeak.net/pypy/extradoc/sprintinfo/tokyo/sprint-announcement.html -.. _`People page`: http://codespeak.net/svn/pypy/extradoc/sprintinfo/tokyo/people.txt +Read more in `the sprint announcement`_, see who is planning to attend +on the `people page`_. There is also a page_ in the python wiki. +.. _`the sprint announcement`: http://codespeak.net/pypy/extradoc/sprintinfo/europython-2006/announce.html +.. _`people page`: http://codespeak.net/pypy/extradoc/sprintinfo/europython-2006/people.html +.. _page: http://wiki.python.org/moin/EuroPython2006 Modified: pypy/dist/pypy/doc/news.txt ============================================================================== --- pypy/dist/pypy/doc/news.txt (original) +++ pypy/dist/pypy/doc/news.txt Tue May 30 12:29:01 2006 @@ -7,6 +7,20 @@ .. _Python: http://www.python.org/doc/current/ref/ref.html .. _`more...`: http://codespeak.net/pypy/dist/pypy/doc/architecture.html#mission-statement + +PyPy and Summer of Code 2006 +================================================================== + +PyPy will again mentor students through Google's `Summer of Code`_ +campaign. Three students will kick-off their work on PyPy by +participating in the Duesseldorf sprint. They will be exploring a +back-end for Microsoft.NET, work on ways to build web applications +with Javascript code (in this case by translating RPython to +Javascript) and porting some CPython modules to use ctypes. Welcome to +the team! + +.. _`Summer of Code`: http://code.google.com/soc/psf/about.html + Duesseldorf PyPy sprint 2-9 June 2006 ================================================================== @@ -21,13 +35,26 @@ .. _`the sprint announcement`: http://codespeak.net/pypy/extradoc/sprintinfo/ddorf2006/announce.html .. _`people page`: http://codespeak.net/pypy/extradoc/sprintinfo/ddorf2006/people.html -PyPy sprint in Tokyo 23rd - 29th April 2006 +PyPy sprint at Akihabara (Tokyo, Japan) ================================================================== -This sprint was in Akihabara, Tokyo, Japan, our hosts was -FSIJ (Free Software Initiative of Japan) and we aimed for the sprint -to promote Python and introduce people to PyPy. Good progress was also made -on PyPy's ootypesystem for the more high level backends. +*April 23rd - 29th 2006.* This sprint was in Akihabara, Tokyo, Japan, +our hosts was FSIJ (Free Software Initiative of Japan) and we aimed +for the sprint to promote Python and introduce people to PyPy. Good +progress was also made on PyPy's ootypesystem for the more high level +backends. For more details, read the last `sprint status`_ page and +enjoy the pictures_. + +.. _`sprint status`: http://codespeak.net/pypy/extradoc/sprintinfo/tokyo/tokyo-planning.html +.. _`pictures`: http://www.flickr.com/photos/19046555 at N00/sets/72057594116388174/ + +PyPy at Python UK/ACCU Conference (United Kingdom) +=================================================================== + +*April 19th - April 22nd 2006.* Several talks about PyPy were hold at +this year's Python UK/ACCU conference. Read more at the `ACCU site`_. + +.. _`ACCU site`: http://www.accu.org/ PyPy at XPDay France 2006 in Paris March 23rd - March 24th 2006 ================================================================== From pedronis at codespeak.net Tue May 30 12:34:25 2006 From: pedronis at codespeak.net (pedronis at codespeak.net) Date: Tue, 30 May 2006 12:34:25 +0200 (CEST) Subject: [pypy-svn] r27904 - pypy/extradoc/talk/dls2006 Message-ID: <20060530103425.AB4DC10057@code0.codespeak.net> Author: pedronis Date: Tue May 30 12:34:24 2006 New Revision: 27904 Modified: pypy/extradoc/talk/dls2006/draft.txt Log: started the experimental result section Modified: pypy/extradoc/talk/dls2006/draft.txt ============================================================================== --- pypy/extradoc/talk/dls2006/draft.txt (original) +++ pypy/extradoc/talk/dls2006/draft.txt Tue May 30 12:34:24 2006 @@ -866,8 +866,33 @@ Experimental results ============================================================ +Our tool-chain is capable of translating the Python interpreter of PyPy, +written in RPython, producing right now ANSI C code as described before, +and also LLVM [#]_ assembler then natively compiled with LLVM tools + +.. [#] the LLVM project is the realisation of a portable assembler + infrastructure, offering both a virtual machine with JIT + capabilities and static compilation. Currently we are using + the latter with its good high-level optimisations for PyPy. + +The tool-chain has been tested and can sucessfully apply +transformations enabling various combinations of features. The +translated interpreters are benchmarked using pystone (a Dhrystone_ +derivative traditionally used by the Python community, although is a +rather poor benchmark) and the classical Richards_ benchmark and +compared against CPython_ 2.4.3 results: + + +Tue May 30 07:58:27 2006 python 2.4.3 789ms ( 1.0x) 40322 ( 1.0x) +Mon May 29 03:07:13 2006 pypy-llvm-27815-x86 5439ms ( 6.9x) 5854 ( 6.9x) +Mon May 29 03:05:52 2006 pypy-llvm-27815-c-prof 2772ms ( 3.5x) 10245 ( 3.9x) +Mon May 29 03:01:46 2006 pypy-llvm-27815-c 3797ms ( 4.8x) 7763 ( 5.2x) +Mon May 29 07:52:36 2006 pypy-c-27815-stackless--_thread 5322ms ( 6.7x) 6016 ( 6.7x) +Mon May 29 06:13:50 2006 pypy-c-27815-stackless 4723ms ( 6.0x) 6527 ( 6.2x) +Mon May 29 05:26:08 2006 pypy-c-27815-gc=framework 6327ms ( 8.0x) 4960 ( 8.1x) +Mon May 29 07:01:06 2006 pypy-c-27815-_thread 4552ms ( 5.8x) 7122 ( 5.7x) +Mon May 29 03:54:04 2006 pypy-c-27815 4269ms ( 5.4x) 7587 ( 5.3x) -XXX @@ -888,7 +913,9 @@ Related work ============================================================ - +Scheme48 VLISP +Squeak +Jikes XXX From ericvrp at codespeak.net Tue May 30 12:52:13 2006 From: ericvrp at codespeak.net (ericvrp at codespeak.net) Date: Tue, 30 May 2006 12:52:13 +0200 (CEST) Subject: [pypy-svn] r27905 - pypy/dist/pypy/objspace/std Message-ID: <20060530105213.69FBE10057@code0.codespeak.net> Author: ericvrp Date: Tue May 30 12:52:07 2006 New Revision: 27905 Modified: pypy/dist/pypy/objspace/std/itertype.py Log: prevent rtyper warnings Modified: pypy/dist/pypy/objspace/std/itertype.py ============================================================================== --- pypy/dist/pypy/objspace/std/itertype.py (original) +++ pypy/dist/pypy/objspace/std/itertype.py Tue May 30 12:52:07 2006 @@ -7,6 +7,8 @@ XXX to do: remove this __reduce__ method and do a registration with copy_reg, instead. """ + from pypy.objspace.std.iterobject import W_SeqIterObject + assert isinstance(w_self, W_SeqIterObject) from pypy.interpreter.mixedmodule import MixedModule w_mod = space.getbuiltinmodule('_pickle_support') mod = space.interp_w(MixedModule, w_mod) @@ -21,6 +23,8 @@ XXX to do: remove this __reduce__ method and do a registration with copy_reg, instead. """ + from pypy.objspace.std.iterobject import W_ReverseSeqIterObject + assert isinstance(w_self, W_ReverseSeqIterObject) from pypy.interpreter.mixedmodule import MixedModule w_mod = space.getbuiltinmodule('_pickle_support') mod = space.interp_w(MixedModule, w_mod) From arigo at codespeak.net Tue May 30 13:07:19 2006 From: arigo at codespeak.net (arigo at codespeak.net) Date: Tue, 30 May 2006 13:07:19 +0200 (CEST) Subject: [pypy-svn] r27906 - pypy/dist/pypy/translator/goal Message-ID: <20060530110719.3428B10053@code0.codespeak.net> Author: arigo Date: Tue May 30 13:07:18 2006 New Revision: 27906 Modified: pypy/dist/pypy/translator/goal/targetvarsized.py Log: Silence a warning. Modified: pypy/dist/pypy/translator/goal/targetvarsized.py ============================================================================== --- pypy/dist/pypy/translator/goal/targetvarsized.py (original) +++ pypy/dist/pypy/translator/goal/targetvarsized.py Tue May 30 13:07:18 2006 @@ -10,6 +10,7 @@ # translate.py targetvarsized.py 20 # DEFAULT_CODE_SIZE_FACTOR = 10 +take_options = True # __________ Entry point __________ From arigo at codespeak.net Tue May 30 13:07:33 2006 From: arigo at codespeak.net (arigo at codespeak.net) Date: Tue, 30 May 2006 13:07:33 +0200 (CEST) Subject: [pypy-svn] r27907 - pypy/dist/pypy/translator/tool Message-ID: <20060530110733.8A24B10063@code0.codespeak.net> Author: arigo Date: Tue May 30 13:07:32 2006 New Revision: 27907 Modified: pypy/dist/pypy/translator/tool/pdbplus.py Log: Don't crash at the end of translation if pygame is not available. Modified: pypy/dist/pypy/translator/tool/pdbplus.py ============================================================================== --- pypy/dist/pypy/translator/tool/pdbplus.py (original) +++ pypy/dist/pypy/translator/tool/pdbplus.py Tue May 30 13:07:32 2006 @@ -440,7 +440,12 @@ port = engraph.port else: return - start, show, stop = server_setup(port) + try: + start, show, stop = server_setup(port) + except Exception, e: + print '%s.%s: %s' % (e.__class__.__module__, + e.__class__.__name__, e) + return self.start(tb, server_setup, graphic=False) self.install_show(show) debugger = self._run_debugger_in_thread(tb, stop) debugger.start() From pedronis at codespeak.net Tue May 30 13:20:29 2006 From: pedronis at codespeak.net (pedronis at codespeak.net) Date: Tue, 30 May 2006 13:20:29 +0200 (CEST) Subject: [pypy-svn] r27908 - pypy/extradoc/talk/dls2006 Message-ID: <20060530112029.78B2810057@code0.codespeak.net> Author: pedronis Date: Tue May 30 13:20:28 2006 New Revision: 27908 Modified: pypy/extradoc/talk/dls2006/draft.txt Log: started related work section Modified: pypy/extradoc/talk/dls2006/draft.txt ============================================================================== --- pypy/extradoc/talk/dls2006/draft.txt (original) +++ pypy/extradoc/talk/dls2006/draft.txt Tue May 30 13:20:28 2006 @@ -913,11 +913,38 @@ Related work ============================================================ -Scheme48 VLISP -Squeak -Jikes -XXX +Applying the expressiveness or at least syntax of very high-level and +dynamically typed languages to their implementation has been +investigated many times. + +One typical approach is writing a static compiler. The viability of +and effort required for such an approach depend usually on the binding +and dispatch semantics of the language. Common Lisp native compilers, +usable interactively and taking functions or files as compilation +units are a well-known example of that approach. Late binding for all +names and load semantics make such an approach very hard for Python, +if speed improvements are desired. + +It is more relevant to consider and compare with projects using +dynamic and very-high level languages for interpreters and VM +implementations, and Just-In-Time compilers. + +Scheme48_ was a Scheme implementation using a restricted Scheme, with +static type inference based on Hindley-Milner, this is viable for +Scheme as base language. Portability and simplicity were its major +goals. + +Squeak_ is a Smalltalk implementation in Smalltalk. It uses SLang, a +very restricted subset of Smalltalk with few types and strict +conventions such that mostly direct translation to C is possible. +Both the VM and the object memory and garbage collector support are +explicitly written together in this style. Again simplicity and +portability were the major goals, not sophisticated manipulation and +analysis and waving in of features. + +Jikes XXX +XXX Jython, IronPython, UVM. .. _`section 8`: From arigo at codespeak.net Tue May 30 14:08:21 2006 From: arigo at codespeak.net (arigo at codespeak.net) Date: Tue, 30 May 2006 14:08:21 +0200 (CEST) Subject: [pypy-svn] r27909 - pypy/extradoc/talk/dls2006 Message-ID: <20060530120821.4502D10057@code0.codespeak.net> Author: arigo Date: Tue May 30 14:08:14 2006 New Revision: 27909 Modified: pypy/extradoc/talk/dls2006/draft.txt Log: Tables and text in Experimental results. Modified: pypy/extradoc/talk/dls2006/draft.txt ============================================================================== --- pypy/extradoc/talk/dls2006/draft.txt (original) +++ pypy/extradoc/talk/dls2006/draft.txt Tue May 30 14:08:14 2006 @@ -143,7 +143,11 @@ calls, and thus only gradually discovers (the reachable parts of) the input program. -``[figure: flow graph and annotator, e.g. part of doc/image/translation.*]`` +:: + + [figure 0: flow graph and annotator, e.g. part of doc/image/translation.* + then a stack of transformations + ] 1. We take as input RPython functions [#]_, and convert them to control flow graphs - a structure amenable to analysis. These flow graphs contain @@ -193,15 +197,15 @@ transformation step produces flow graphs that also assume automatic memory management. Generating C code directly from there produces a fully leaking program, unless we link it with an external garbage -collector (GC) like the Boehm conservative GC [Boehm], which is a viable -option. +collector (GC) like the Boehm conservative GC `[Boehm]`_, which is a +viable option. We have two alternatives, each implemented as a transformation step. The first one inserts naive reference counting throughout the whole program's graphs, which without further optimizations gives exceedingly bad performance (it should be noted that the CPython interpreter is also based on reference counting, and experience suggests that it was not a -bad choice in this particular case; more in `section 5`_). +bad choice in this particular case). The other, and better, alternative is an exact GC, coupled with a transformation, the *GC transformer*. It inputs C-level-typed graphs @@ -867,32 +871,134 @@ ============================================================ Our tool-chain is capable of translating the Python interpreter of PyPy, -written in RPython, producing right now ANSI C code as described before, -and also LLVM [#]_ assembler then natively compiled with LLVM tools +written in RPython, producing right now either ANSI C code as described +before, or LLVM [#]_ assembler which is then natively compiled with LLVM +tools. .. [#] the LLVM project is the realisation of a portable assembler infrastructure, offering both a virtual machine with JIT capabilities and static compilation. Currently we are using the latter with its good high-level optimisations for PyPy. -The tool-chain has been tested and can sucessfully apply +The tool-chain has been tested with and can sucessfully apply transformations enabling various combinations of features. The translated interpreters are benchmarked using pystone (a Dhrystone_ -derivative traditionally used by the Python community, although is a +derivative traditionally used by the Python community, although it is a rather poor benchmark) and the classical Richards_ benchmark and compared against CPython_ 2.4.3 results: - -Tue May 30 07:58:27 2006 python 2.4.3 789ms ( 1.0x) 40322 ( 1.0x) -Mon May 29 03:07:13 2006 pypy-llvm-27815-x86 5439ms ( 6.9x) 5854 ( 6.9x) -Mon May 29 03:05:52 2006 pypy-llvm-27815-c-prof 2772ms ( 3.5x) 10245 ( 3.9x) -Mon May 29 03:01:46 2006 pypy-llvm-27815-c 3797ms ( 4.8x) 7763 ( 5.2x) -Mon May 29 07:52:36 2006 pypy-c-27815-stackless--_thread 5322ms ( 6.7x) 6016 ( 6.7x) -Mon May 29 06:13:50 2006 pypy-c-27815-stackless 4723ms ( 6.0x) 6527 ( 6.2x) -Mon May 29 05:26:08 2006 pypy-c-27815-gc=framework 6327ms ( 8.0x) 4960 ( 8.1x) -Mon May 29 07:01:06 2006 pypy-c-27815-_thread 4552ms ( 5.8x) 7122 ( 5.7x) -Mon May 29 03:54:04 2006 pypy-c-27815 4269ms ( 5.4x) 7587 ( 5.3x) - ++------------------------------------+-------------------+-------------------+ +| Interpreter | Richards, | Pystone, | +| | Time/iteration | Iterations/second | ++====================================+===================+===================+ +| CPython 2.4.3 | 789ms (1.0x) | 40322 (1.0x) | ++------------------------------------+-------------------+-------------------+ +| pypy-c | 4269ms (5.4x) | 7587 (5.3x) | ++------------------------------------+-------------------+-------------------+ +| pypy-c-thread | 4552ms (5.8x) | 7122 (5.7x) | ++------------------------------------+-------------------+-------------------+ +| pypy-c-stackless | XXX (6.0x) | XXX (6.2x) | ++------------------------------------+-------------------+-------------------+ +| pypy-c-gcframework | 6327ms (8.0x) | 4960 (8.1x) | ++------------------------------------+-------------------+-------------------+ +| pypy-c-stackless-gcframework | XXX ( ) | XXX ( ) | ++------------------------------------+-------------------+-------------------+ +| pypy-llvm-c | 3797ms (4.8x) | 7763 (5.2x) | ++------------------------------------+-------------------+-------------------+ +| pypy-llvm-c-prof | 2772ms (3.5x) | 10245 (3.9x) | ++------------------------------------+-------------------+-------------------+ + +The numbers in parenthesis are slow-down factors compared to CPython. +These measures reflect PyPy revision 27815, compiled with GCC 3.4.4. +LLVM is version 1.8cvs (May 11, 2006). The machine runs GNU/Linux SMP +on an Intel(R) Pentium(R) 4 CPU at 3.20GHz with 2GB of RAM and 1MB of +cache. The rows correspond to variants of the translation process, as +follows: + +pypy-c + The simplest variant: translated to C code with no explicit memory + management, and linked with the Boehm conservative GC `[Boehm]`_. + +pypy-c-thread + The same, with OS thread support enabled. (For measurement purposes, + thread support is kept separate because it has an impact on the GC + performance.) + +pypy-c-stackless + The same as pypy-c, plus the "stackless transformation" step which + modifies the flow graph of all functions in a way that allows them + to save and restore their local state, as a way to enable coroutines. + +pypy-c-gcframework + In this variant, the "gc transformation" step inserts explicit + memory management and a simple mark-and-sweep GC implementation. + The resulting program is not linked with Boehm. Note that it is not + possible to find all roots from the C stack in portable C; instead, + in this variant each function explicitly pushes and pops all roots + to an alternate stack around each subcall. + +pypy-c-stackless-gcframework + This variant combines the "gc transformation" step with the + "stackless transformation" step. The overhead introduced by the + stackless feature is balanced with the removal of the overhead of + pushing and popping roots explicitly on an alternate stack: indeed, + in this variant it is possible to ask the functions in the current C + call chain to save their local state and return. This has the + side-effect of moving all roots to the heap, where the GC can find + them. + +pypy-llvm-c + The same as pypy-c, but using the LLVM back-end instead of the C + back-end. The LLVM assembler-compiler gives the best results when - + as we do here - it optimizes its input and generates again C code, + which is fed to GCC. + +pypy-llvm-c-prof + The same as pypy-llvm-c, but using GCC's profile-driven + optimizations. + +XXX explain slow. + +The complete translation of the pypy-c variant takes about 39 minutes, +divided as follows: + ++-------------------------------------------+------------------------------+ +| Step | Time (minutes:seconds) | ++===========================================+==============================+ +| Front-end | 9:01 | +| (flow graphs and type inference) | | ++-------------------------------------------+------------------------------+ +| LLTyper | 10:38 | +| (from RPython-level to C-level graphs | | +| and data) | | ++-------------------------------------------+------------------------------+ +| Various low-level optimizations | 6:51 | +| (convert some heap allocations to local | | +| variables, inlining, ...) | | ++-------------------------------------------+------------------------------+ +| Database building | 8:39 | +| (this initial back-end step follows all | | +| graphs and prebuilt data structures | | +| recursively, assigns names, and orders | | +| them suitably for code generation) | | ++-------------------------------------------+------------------------------+ +| Generating C source | 2:25 | ++-------------------------------------------+------------------------------+ +| Compiling (``gcc -O2``) | 3:23 | ++-------------------------------------------+------------------------------+ + +An interesting feature of this table is that type inference is not the +bottleneck. Indeed, further transformation steps typically take longer +than type inference alone. This is the case for the LLTyper step, +although it has a linear complexity on the size of its input (most +transformations do). + +Other transformations like the "gc" and the "stackless" ones actually +take more time, particuarly when used in combination with each other (we +speculate it is because of the increase in size caused by the previous +transformations). A translation of pypy-c-stackless, without counting +GCC time, takes 60 minutes; the same for pypy-c-stackless-gcframework +takes XXX minutes. From pedronis at codespeak.net Tue May 30 14:13:39 2006 From: pedronis at codespeak.net (pedronis at codespeak.net) Date: Tue, 30 May 2006 14:13:39 +0200 (CEST) Subject: [pypy-svn] r27910 - pypy/extradoc/talk/dls2006 Message-ID: <20060530121339.E12CD10057@code0.codespeak.net> Author: pedronis Date: Tue May 30 14:13:39 2006 New Revision: 27910 Modified: pypy/extradoc/talk/dls2006/draft.txt Log: some more of the related work section. Modified: pypy/extradoc/talk/dls2006/draft.txt ============================================================================== --- pypy/extradoc/talk/dls2006/draft.txt (original) +++ pypy/extradoc/talk/dls2006/draft.txt Tue May 30 14:13:39 2006 @@ -1048,7 +1048,34 @@ portability were the major goals, not sophisticated manipulation and analysis and waving in of features. -Jikes XXX +`Jikes RVM`_ is a Java VM and Just-In-Time compiler written in Java. +Bootstrapping happens by self-applying the compiler on a host VM, and +dumping a snapshot from memory of the resulting native code. + +This approach enables directly high performance, at the price of +portability as usual with pure native code emitting +approaches. Modularity of features, when possible, is achieved with +normal software modularity. The indirection costs are taken care by +the inlining done by the compiler, sometimes even through explicit +ways to request for it. In particular this modular approach is used +for implementing a range of choices for GC support XXX ref. This was +the inspiration for PyPy own GC framework, although much more tuning +and work went into Jikes RVM. PyPy own GC framework also exploits +inlining of helpers and barriers to recover performance. + +Jikes RVM native JIT compilers can likely not easily be retargeted to +run on top and target another VM (for example a CLR runtime) instead +of hardware processors. Also Jikes RVM pays the complexity of writing +a JIT up-front, which also means that features and semantics of the +language are encoded in the JIT compiler code, meaning likely that +major changes would correspond to major surgery needed on it. + +PyPy more indirect approach, together hopefully with our future work +on generating a JIT compiler, tries to overcome these limitations, at +the price of some more effort required to achieve very good +performance. It is too soon to compare completely the complexity (and +performance) trade-offs of these approaches. + XXX Jython, IronPython, UVM. From arigo at codespeak.net Tue May 30 14:20:59 2006 From: arigo at codespeak.net (arigo at codespeak.net) Date: Tue, 30 May 2006 14:20:59 +0200 (CEST) Subject: [pypy-svn] r27912 - pypy/extradoc/talk/dls2006 Message-ID: <20060530122059.AB7771005A@code0.codespeak.net> Author: arigo Date: Tue May 30 14:20:58 2006 New Revision: 27912 Modified: pypy/extradoc/talk/dls2006/draft.txt Log: Explained slow. Modified: pypy/extradoc/talk/dls2006/draft.txt ============================================================================== --- pypy/extradoc/talk/dls2006/draft.txt (original) +++ pypy/extradoc/talk/dls2006/draft.txt Tue May 30 14:20:58 2006 @@ -870,6 +870,10 @@ Experimental results ============================================================ + +Performance +----------- + Our tool-chain is capable of translating the Python interpreter of PyPy, written in RPython, producing right now either ANSI C code as described before, or LLVM [#]_ assembler which is then natively compiled with LLVM @@ -957,9 +961,24 @@ The same as pypy-llvm-c, but using GCC's profile-driven optimizations. -XXX explain slow. +The speed difference with CPython 2.4.3 can be explained at two levels. +One is that CPython is hand-crafted C code that has been continuously +optimized for a decade now, whereas the Python interpreter of PyPy first +seeks flexibility and high abstraction levels. The other, probably +dominant, factor is that various indices show that our approach places a +very high load on the GC and on the memory caches of the machine. The +Boehm GC is known to be less efficient than more customized approach; +kernel-level profiling shows that pypy-c typically spends 30% of its +time in the Boehm library. Our current, naively simple mark-and-sweep +GC is even quite worse. The interaction with processor caches is also +hard to predict and account for; in general, we tend to produce +relatively large amounts of code and prebuilt data. + + +Translation times +----------------- -The complete translation of the pypy-c variant takes about 39 minutes, +A complete translation of the pypy-c variant takes about 39 minutes, divided as follows: +-------------------------------------------+------------------------------+ From ac at codespeak.net Tue May 30 14:30:29 2006 From: ac at codespeak.net (ac at codespeak.net) Date: Tue, 30 May 2006 14:30:29 +0200 (CEST) Subject: [pypy-svn] r27914 - in pypy/dist/pypy: module/unicodedata objspace/std Message-ID: <20060530123029.DABEE10057@code0.codespeak.net> Author: ac Date: Tue May 30 14:30:29 2006 New Revision: 27914 Added: pypy/dist/pypy/module/unicodedata/interp_ucd.py - copied unchanged from r27913, pypy/dist/pypy/module/unicodedata/function.py Removed: pypy/dist/pypy/module/unicodedata/function.py Modified: pypy/dist/pypy/module/unicodedata/__init__.py pypy/dist/pypy/objspace/std/unicodeobject.py Log: Some renaming. Modified: pypy/dist/pypy/module/unicodedata/__init__.py ============================================================================== --- pypy/dist/pypy/module/unicodedata/__init__.py (original) +++ pypy/dist/pypy/module/unicodedata/__init__.py Tue May 30 14:30:29 2006 @@ -4,14 +4,14 @@ appleveldefs = { } interpleveldefs = { - 'unidata_version' : 'space.wrap(function.ucd.version)', - 'ucd_3_2_0' : 'space.wrap(function.ucd_3_2_0)', - 'ucd_4_1_0' : 'space.wrap(function.ucd_4_1_0)', - 'ucd' : 'space.wrap(function.ucd)', + 'unidata_version' : 'space.wrap(interp_ucd.ucd.version)', + 'ucd_3_2_0' : 'space.wrap(interp_ucd.ucd_3_2_0)', + 'ucd_4_1_0' : 'space.wrap(interp_ucd.ucd_4_1_0)', + 'ucd' : 'space.wrap(interp_ucd.ucd)', '__doc__' : "space.wrap('unicode character database')", } for name in '''lookup name decimal digit numeric category bidirectional east_asian_width combining mirrored decomposition normalize'''.split(): - interpleveldefs[name] = '''space.getattr(space.wrap(function.ucd), + interpleveldefs[name] = '''space.getattr(space.wrap(interp_ucd.ucd), space.wrap("%s"))''' % name Modified: pypy/dist/pypy/objspace/std/unicodeobject.py ============================================================================== --- pypy/dist/pypy/objspace/std/unicodeobject.py (original) +++ pypy/dist/pypy/objspace/std/unicodeobject.py Tue May 30 14:30:29 2006 @@ -4,7 +4,9 @@ from pypy.objspace.std.noneobject import W_NoneObject from pypy.objspace.std.sliceobject import W_SliceObject from pypy.rpython.rarithmetic import intmask -from pypy.module.unicodedata import unicodedb +from pypy.module.unicodedata.interp_ucd import ucd + +unicodedb = ucd.unicodedb class W_UnicodeObject(W_Object): from pypy.objspace.std.unicodetype import unicode_typedef as typedef From arigo at codespeak.net Tue May 30 15:53:03 2006 From: arigo at codespeak.net (arigo at codespeak.net) Date: Tue, 30 May 2006 15:53:03 +0200 (CEST) Subject: [pypy-svn] r27917 - pypy/extradoc/talk/dls2006 Message-ID: <20060530135303.50F5B10063@code0.codespeak.net> Author: arigo Date: Tue May 30 15:53:02 2006 New Revision: 27917 Modified: pypy/extradoc/talk/dls2006/draft.txt Log: ReST fixes. Modified: pypy/extradoc/talk/dls2006/draft.txt ============================================================================== --- pypy/extradoc/talk/dls2006/draft.txt (original) +++ pypy/extradoc/talk/dls2006/draft.txt Tue May 30 15:53:02 2006 @@ -989,17 +989,17 @@ +-------------------------------------------+------------------------------+ | LLTyper | 10:38 | | (from RPython-level to C-level graphs | | -| and data) | | +| and data) | | +-------------------------------------------+------------------------------+ | Various low-level optimizations | 6:51 | | (convert some heap allocations to local | | -| variables, inlining, ...) | | +| variables, inlining, ...) | | +-------------------------------------------+------------------------------+ | Database building | 8:39 | | (this initial back-end step follows all | | -| graphs and prebuilt data structures | | -| recursively, assigns names, and orders | | -| them suitably for code generation) | | +| graphs and prebuilt data structures | | +| recursively, assigns names, and orders | | +| them suitably for code generation) | | +-------------------------------------------+------------------------------+ | Generating C source | 2:25 | +-------------------------------------------+------------------------------+ @@ -1117,6 +1117,13 @@ .. _`Hindley-Milner`: http://en.wikipedia.org/wiki/Hindley-Milner_type_inference .. _`join-semilattice`: http://en.wikipedia.org/wiki/Semilattice .. _SSA: http://en.wikipedia.org/wiki/Static_single_assignment_form +.. _`[Boehm]`: XXX +.. _Dhrystone: XXX +.. _Richards: XXX +.. _CPython: XXX +.. _Scheme48: XXX +.. _Squeak: XXX +.. _`Jikes RVM`: XXX .. http://www.cs.jhu.edu/~scott/pll/constraints.html page to the reference /recent result for constraint-based type inference From hpk at codespeak.net Tue May 30 15:57:05 2006 From: hpk at codespeak.net (hpk at codespeak.net) Date: Tue, 30 May 2006 15:57:05 +0200 (CEST) Subject: [pypy-svn] r27918 - pypy/dist/pypy/module/unicodedata Message-ID: <20060530135705.0C5C910064@code0.codespeak.net> Author: hpk Date: Tue May 30 15:57:00 2006 New Revision: 27918 Modified: pypy/dist/pypy/module/unicodedata/interp_ucd.py Log: fixing a leftover line (i guess), making translation break Modified: pypy/dist/pypy/module/unicodedata/interp_ucd.py ============================================================================== --- pypy/dist/pypy/module/unicodedata/interp_ucd.py (original) +++ pypy/dist/pypy/module/unicodedata/interp_ucd.py Tue May 30 15:57:00 2006 @@ -120,7 +120,6 @@ decomposition.unwrap_spec = ['self', ObjSpace, W_Root] def normalize(self, space, 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': From ac at codespeak.net Tue May 30 16:10:46 2006 From: ac at codespeak.net (ac at codespeak.net) Date: Tue, 30 May 2006 16:10:46 +0200 (CEST) Subject: [pypy-svn] r27920 - in pypy/dist/pypy: module/unicodedata objspace/std Message-ID: <20060530141046.99B7E10053@code0.codespeak.net> Author: ac Date: Tue May 30 16:10:46 2006 New Revision: 27920 Modified: pypy/dist/pypy/module/unicodedata/interp_ucd.py pypy/dist/pypy/objspace/std/unicodeobject.py Log: Fix translation. Modified: pypy/dist/pypy/module/unicodedata/interp_ucd.py ============================================================================== --- pypy/dist/pypy/module/unicodedata/interp_ucd.py (original) +++ pypy/dist/pypy/module/unicodedata/interp_ucd.py Tue May 30 16:10:46 2006 @@ -29,12 +29,28 @@ class UCD(Wrappable): def __init__(self, unicodedb): - self.unicodedb = unicodedb + self._lookup = unicodedb.lookup + self._name = unicodedb.name + self._decimal = unicodedb.decimal + self._digit = unicodedb.digit + self._numeric = unicodedb.numeric + self._category = unicodedb.category + self._east_asian_width = unicodedb.east_asian_width + self._bidirectional = unicodedb.bidirectional + self._combining = unicodedb.combining + self._mirrored = unicodedb.mirrored + self._decomposition = unicodedb.decomposition + self._canon_decomposition = unicodedb._canon_decomposition + self._compat_decomposition = unicodedb._compat_decomposition + self._composition_max = unicodedb._composition_max + self._composition_shift = unicodedb._composition_shift + self._composition = unicodedb._composition + self.version = unicodedb.version def lookup(self, space, name): try: - code = self.unicodedb.lookup(name) + code = self._lookup(name) except KeyError: msg = space.mod(space.wrap("undefined character name '%s'"), space.wrap(name)) raise OperationError(space.w_KeyError, msg) @@ -46,7 +62,7 @@ def name(self, space, w_unichr, w_default=NoneNotWrapped): code = unichr_to_code_w(space, w_unichr) try: - name = self.unicodedb.name(code) + name = self._name(code) except KeyError: if w_default is not None: return w_default @@ -58,7 +74,7 @@ def decimal(self, space, w_unichr, w_default=NoneNotWrapped): code = unichr_to_code_w(space, w_unichr) try: - return space.wrap(self.unicodedb.decimal(code)) + return space.wrap(self._decimal(code)) except KeyError: pass if w_default is not None: @@ -69,7 +85,7 @@ def digit(self, space, w_unichr, w_default=NoneNotWrapped): code = unichr_to_code_w(space, w_unichr) try: - return space.wrap(self.unicodedb.digit(code)) + return space.wrap(self._digit(code)) except KeyError: pass if w_default is not None: @@ -80,7 +96,7 @@ def numeric(self, space, w_unichr, w_default=NoneNotWrapped): code = unichr_to_code_w(space, w_unichr) try: - return space.wrap(self.unicodedb.numeric(code)) + return space.wrap(self._numeric(code)) except KeyError: pass if w_default is not None: @@ -91,32 +107,32 @@ def category(self, space, w_unichr): code = unichr_to_code_w(space, w_unichr) - return space.wrap(self.unicodedb.category(code)) + return space.wrap(self._category(code)) category.unwrap_spec = ['self', ObjSpace, W_Root] def east_asian_width(self, space, w_unichr): code = unichr_to_code_w(space, w_unichr) - return space.wrap(self.unicodedb.east_asian_width(code)) + return space.wrap(self._east_asian_width(code)) east_asian_width.unwrap_spec = ['self', ObjSpace, W_Root] def bidirectional(self, space, w_unichr): code = unichr_to_code_w(space, w_unichr) - return space.wrap(self.unicodedb.bidirectional(code)) + return space.wrap(self._bidirectional(code)) bidirectional.unwrap_spec = ['self', ObjSpace, W_Root] def combining(self, space, w_unichr): code = unichr_to_code_w(space, w_unichr) - return space.wrap(self.unicodedb.combining(code)) + return space.wrap(self._combining(code)) combining.unwrap_spec = ['self', ObjSpace, W_Root] def mirrored(self, space, w_unichr): code = unichr_to_code_w(space, w_unichr) - return space.wrap(self.unicodedb.mirrored(code)) + return space.wrap(self._mirrored(code)) mirrored.unwrap_spec = ['self', ObjSpace, W_Root] def decomposition(self, space, w_unichr): code = unichr_to_code_w(space, w_unichr) - return space.wrap(self.unicodedb.decomposition(code)) + return space.wrap(self._decomposition(code)) decomposition.unwrap_spec = ['self', ObjSpace, W_Root] def normalize(self, space, form, w_unistr): @@ -124,16 +140,16 @@ raise TypeError, 'argument 2 must be unicode' if form == 'NFC': composed = True - decomposition = self.unicodedb._canon_decomposition + decomposition = self._canon_decomposition elif form == 'NFD': composed = False - decomposition = self.unicodedb._canon_decomposition + decomposition = self._canon_decomposition elif form == 'NFKC': composed = True - decomposition = self.unicodedb._compat_decomposition + decomposition = self._compat_decomposition elif form == 'NFKD': composed = False - decomposition = self.unicodedb._compat_decomposition + decomposition = self._compat_decomposition else: raise OperationError(space.w_ValueError, space.wrap('invalid normalization form')) @@ -186,11 +202,11 @@ # Sort all combining marks for i in range(j): ch = result[i] - comb = self.unicodedb.combining(ch) + comb = self._combining(ch) if comb == 0: continue for k in range(i, 0, -1): - if self.unicodedb.combining(result[k - 1]) <= comb: + if self._combining(result[k - 1]) <= comb: result[k] = ch break @@ -208,11 +224,11 @@ starter_pos = 0 next_insert = 1 prev_combining = 0 - if self.unicodedb.combining(current): + if self._combining(current): prev_combining = 256 for k in range(1, j): next = result[k] - next_combining = self.unicodedb.combining(next) + next_combining = self._combining(next) if next_insert == starter_pos + 1 or prev_combining < next_combining: # Combine if not blocked if (LBase <= current < LBase + LCount and @@ -226,11 +242,11 @@ # If LV, T -> LVT current = current + (next - TBase) continue - if (current <= self.unicodedb._composition_max and - next <= self.unicodedb._composition_max): - key = current << self.unicodedb._composition_shift | next + if (current <= self._composition_max and + next <= self._composition_max): + key = current << self._composition_shift | next try: - current = self.unicodedb._composition[key] + current = self._composition[key] continue except KeyError: pass Modified: pypy/dist/pypy/objspace/std/unicodeobject.py ============================================================================== --- pypy/dist/pypy/objspace/std/unicodeobject.py (original) +++ pypy/dist/pypy/objspace/std/unicodeobject.py Tue May 30 16:10:46 2006 @@ -4,9 +4,7 @@ from pypy.objspace.std.noneobject import W_NoneObject from pypy.objspace.std.sliceobject import W_SliceObject from pypy.rpython.rarithmetic import intmask -from pypy.module.unicodedata.interp_ucd import ucd - -unicodedb = ucd.unicodedb +from pypy.module.unicodedata import unicodedb_4_1_0 as unicodedb class W_UnicodeObject(W_Object): from pypy.objspace.std.unicodetype import unicode_typedef as typedef From arigo at codespeak.net Tue May 30 17:08:03 2006 From: arigo at codespeak.net (arigo at codespeak.net) Date: Tue, 30 May 2006 17:08:03 +0200 (CEST) Subject: [pypy-svn] r27922 - pypy/extradoc/talk/dls2006 Message-ID: <20060530150803.D446510036@code0.codespeak.net> Author: arigo Date: Tue May 30 17:08:02 2006 New Revision: 27922 Modified: pypy/extradoc/talk/dls2006/draft.txt Log: Future work, and a conclusion outline. Modified: pypy/extradoc/talk/dls2006/draft.txt ============================================================================== --- pypy/extradoc/talk/dls2006/draft.txt (original) +++ pypy/extradoc/talk/dls2006/draft.txt Tue May 30 17:08:02 2006 @@ -12,7 +12,7 @@ The aim is to translate (i.e. compile) the VM to arbitrary target environments, ranging in level from C/Posix to Smalltalk/Squeak via Java and CLI/.NET, while still being of reasonable efficiency within - that environment. + these environments. A key tool to achieve this goal is the systematic reuse of the (unmodified, dynamically typed) Python language as a system @@ -1028,7 +1028,43 @@ ============================================================ -XXX +As described in `section 5`_, the performance of the compiled Python +interpreters is still not up to competing with the well-established +CPython. We are always working to improve matters, considering new +optimizations and better GCs. Also, the OOTyper and back-ends for +Smalltalk/Squeak and CLI/.NET are currently in progress. + + +JIT Specializer +--------------- + +So far, the PyPy tool-chain can only translate the Python interpreter of +PyPy into a program which is again an interpreter - the same interpreter +translated to C, essentially, although we have already shown that some +aspects can be "weaved" in at translation time, like support for +coroutines. + +To achieve high performance for dynamic languages such as Python, the +proven approach is to use dynamic compilation techniques, i.e. to write +JITs. With direct techniques, this is however a major endeavour, and +increases the efforts to further evolve the language. + +In the context of the PyPy project, we are now exploring - as we planned +from the start - the possibility to produce a JIT as a graph +transformation aspect from the Python interpreter. This idea is based +on the theoretical possibiliy to turn interpreters into compilers by +partial evaluation `[PE]`_. In our approach, this is done by analysing +the forest of flow graphs built from the Python interpreter, which is a +well-suited input for this kind of techniques. We can currently perform +binding-time analysis `[BTA]`_ on these graphs, again with abstract +interpretation techniques reusing the type inference engine. The next +step is to transform the graphs - following the binding-time annotations +- into a compiler; more precisely, in partial evalution terminology, a +generating extension. We can currently do this on trivial examples. + +The resulting generating extension will be essentially similar to +Psyco_, which is the only (and hand-written) JIT available for Python so +far, based on run-time specialization. @@ -1108,15 +1144,29 @@ XXX +nice interpreter not polluted by implementation details +here Python, but any interpreter works + +architecture allows implementing features at the right level + +dynamic language enables defining our own various type systems +[ref pluggable type systems] + +practical VMs will result with a bit more efforts + + + +References +---------- .. _`[D]`: http://codespeak.net/pypy/dist/pypy/doc/dynamic-language-translation.html .. _`[S]`: http://codespeak.net/pypy/dist/pypy/doc/architecture.html#the-standard-interpreter .. _`[T]`: http://codespeak.net/pypy/dist/pypy/doc/translation.html -.. _`abstract interpretation`: http://en.wikipedia.org/wiki/Abstract_interpretation +.. _`abstract interpretation`: XXX http://en.wikipedia.org/wiki/Abstract_interpretation .. _Graphviz: http://www.graphviz.org/ -.. _`Hindley-Milner`: http://en.wikipedia.org/wiki/Hindley-Milner_type_inference -.. _`join-semilattice`: http://en.wikipedia.org/wiki/Semilattice -.. _SSA: http://en.wikipedia.org/wiki/Static_single_assignment_form +.. _`Hindley-Milner`: XXX http://en.wikipedia.org/wiki/Hindley-Milner_type_inference +.. _`join-semilattice`: XXX http://en.wikipedia.org/wiki/Semilattice +.. _SSA: XXX http://en.wikipedia.org/wiki/Static_single_assignment_form .. _`[Boehm]`: XXX .. _Dhrystone: XXX .. _Richards: XXX @@ -1124,6 +1174,9 @@ .. _Scheme48: XXX .. _Squeak: XXX .. _`Jikes RVM`: XXX +.. _`[PE]`: XXX +.. _`[BTA]`: XXX +.. _Psyco: XXX .. http://www.cs.jhu.edu/~scott/pll/constraints.html page to the reference /recent result for constraint-based type inference From mwh at codespeak.net Tue May 30 17:09:57 2006 From: mwh at codespeak.net (mwh at codespeak.net) Date: Tue, 30 May 2006 17:09:57 +0200 (CEST) Subject: [pypy-svn] r27923 - pypy/extradoc/talk/dls2006 Message-ID: <20060530150957.A8AAE10053@code0.codespeak.net> Author: mwh Date: Tue May 30 17:09:55 2006 New Revision: 27923 Added: pypy/extradoc/talk/dls2006/acm_proc_article-sp.cls Log: add the acm class file. Added: pypy/extradoc/talk/dls2006/acm_proc_article-sp.cls ============================================================================== --- (empty file) +++ pypy/extradoc/talk/dls2006/acm_proc_article-sp.cls Tue May 30 17:09:55 2006 @@ -0,0 +1,1391 @@ +% ACM_PROC_ARTICLE-SP.CLS - VERSION 2.7SP +% COMPATIBLE WITH THE "ACM_PROC_ARTICLE.CLS" V2.5 +% Gerald Murray October 15th., 2004 +% +% ---- Start of 'updates' ---- +% +% Allowance made to switch default fonts between those systems using +% METAFONT and those using 'Type 1' or 'Truetype' fonts. +% See LINE NUMBER 266 for details. +% Also provided for enumerated/annotated Corollaries 'surrounded' by +% enumerated Theorems (line 838). +% Gerry November 11th. 1999 +% +% Made the Permission Statement / Conference Info / Copyright Info +% 'user definable' in the source .tex file OR automatic if +% not specified. +% This 'sp' version does NOT produce the permission block. +% +% Major change in January 2000 was to include a "blank line" in between +% new paragraphs. This involved major changes to the, then, acmproc-sp.cls 1.0SP +% file, precipitating a 'new' name: "acm_proc_article-sp.cls" V2.01SP. +% +% Georgia fixed bug in sub-sub-section numbering in paragraphs (July 29th. 2002) +% JS/GM fix to vertical spacing before Proofs (July 30th. 2002) +% +% Footnotes inside table cells using \minipage (Oct. 2002) +% +% ---- End of 'updates' ---- +% +\def\fileversion{V2.7SP} % for ACM's tracking purposes +\def\filedate{October 15, 2004} % Gerry Murray's tracking data +\def\docdate {Friday 15th. October 2004} % Gerry Murray (with deltas to doc} +\usepackage{epsfig} +\usepackage{amssymb} +\usepackage{amsmath} +\usepackage{amsfonts} +% +% ACM_PROC_ARTICLE-SP DOCUMENT STYLE +% G.K.M. Tobin August-October 1999 +% adapted from ARTICLE document style by Ken Traub, Olin Shivers +% also using elements of esub2acm.cls +% LATEST REVISION V2.7SP - OCTOBER 2004 +% ARTICLE DOCUMENT STYLE -- Released 16 March 1988 +% for LaTeX version 2.09 +% Copyright (C) 1988 by Leslie Lamport +% +% +%%% ACM_PROC_ARTICLE-SP is a document style for producing two-column camera-ready pages for +%%% ACM conferences, according to ACM specifications. The main features of +%%% this style are: +%%% +%%% 1) Two columns. +%%% 2) Side and top margins of 4.5pc, bottom margin of 6pc, column gutter of +%%% 2pc, hence columns are 20pc wide and 55.5pc tall. (6pc =3D 1in, approx) +%%% 3) First page has title information, and an extra 6pc of space at the +%%% bottom of the first column for the ACM copyright notice. +%%% 4) Text is 9pt on 10pt baselines; titles (except main) are 9pt bold. +%%% +%%% +%%% There are a few restrictions you must observe: +%%% +%%% 1) You cannot change the font size; ACM wants you to use 9pt. +%%% 3) You must start your paper with the \maketitle command. Prior to the +%%% \maketitle you must have \title and \author commands. If you have a +%%% \date command it will be ignored; no date appears on the paper, since +%%% the proceedings will have a date on the front cover. +%%% 4) Marginal paragraphs, tables of contents, lists of figures and tables, +%%% and page headings are all forbidden. +%%% 5) The `figure' environment will produce a figure one column wide; if you +%%% want one that is two columns wide, use `figure*'. +%%% +% +%%% Copyright Space: +%%% This style automatically leaves 1" blank space at the bottom of page 1/ +%%% column 1. This space can optionally be filled with some text using the +%%% \toappear{...} command. If used, this command must be BEFORE the \maketitle +%%% command. If this command is defined AND [preprint] is on, then the +%%% space is filled with the {...} text (at the bottom); otherwise, it is +%%% blank. If you use \toappearbox{...} instead of \toappear{...} then a +%%% box will be drawn around the text (if [preprint] is on). +%%% +%%% A typical usage looks like this: +%%% \toappear{To appear in the Ninth AES Conference on Medievil Lithuanian +%%% Embalming Technique, June 1991, Alfaretta, Georgia.} +%%% This will be included in the preprint, and left out of the conference +%%% version. +%%% +%%% WARNING: +%%% Some dvi-ps converters heuristically allow chars to drift from their +%%% true positions a few pixels. This may be noticeable with the 9pt sans-serif +%%% bold font used for section headers. +%%% You may turn this hackery off via the -e option: +%%% dvips -e 0 foo.dvi >foo.ps +%%% +\typeout{Document Class 'acm_proc_article-sp' <15th. October '04>. Modified by G.K.M. Tobin} +\typeout{Based in part upon document Style `acmconf' <22 May 89>. Hacked 4/91 by} +\typeout{shivers at cs.cmu.edu, 4/93 by theobald at cs.mcgill.ca} +\typeout{Excerpts were taken from (Journal Style) 'esub2acm.cls'.} +\typeout{****** Bugs/comments/suggestions to Gerry Murray -- murray at hq.acm.org ******} + +\oddsidemargin 4.5pc +\evensidemargin 4.5pc +\advance\oddsidemargin by -1in % Correct for LaTeX gratuitousness +\advance\evensidemargin by -1in % Correct for LaTeX gratuitousness +\marginparwidth 0pt % Margin pars are not allowed. +\marginparsep 11pt % Horizontal space between outer margin and + % marginal note + + % Top of page: +\topmargin 4.5pc % Nominal distance from top of page to top of + % box containing running head. +\advance\topmargin by -1in % Correct for LaTeX gratuitousness +\headheight 0pt % Height of box containing running head. +\headsep 0pt % Space between running head and text. + % Bottom of page: +\footskip 30pt % Distance from baseline of box containing foot + % to baseline of last line of text. +\@ifundefined{footheight}{\newdimen\footheight}{}% this is for LaTeX2e +\footheight 12pt % Height of box containing running foot. + + +%% Must redefine the top margin so there's room for headers and +%% page numbers if you are using the preprint option. Footers +%% are OK as is. Olin. +\advance\topmargin by -37pt % Leave 37pt above text for headers +\headheight 12pt % Height of box containing running head. +\headsep 25pt % Space between running head and text. + +\textheight 666pt % 9 1/4 column height +\textwidth 42pc % Width of text line. + % For two-column mode: +\columnsep 2pc % Space between columns +\columnseprule 0pt % Width of rule between columns. +\hfuzz 1pt % Allow some variation in column width, otherwise it's + % too hard to typeset in narrow columns. + +\footnotesep 5.6pt % Height of strut placed at the beginning of every + % footnote =3D height of normal \footnotesize strut, + % so no extra space between footnotes. + +\skip\footins 8.1pt plus 4pt minus 2pt % Space between last line of text and + % top of first footnote. +\floatsep 11pt plus 2pt minus 2pt % Space between adjacent floats moved + % to top or bottom of text page. +\textfloatsep 18pt plus 2pt minus 4pt % Space between main text and floats + % at top or bottom of page. +\intextsep 11pt plus 2pt minus 2pt % Space between in-text figures and + % text. +\@ifundefined{@maxsep}{\newdimen\@maxsep}{}% this is for LaTeX2e +\@maxsep 18pt % The maximum of \floatsep, + % \textfloatsep and \intextsep (minus + % the stretch and shrink). +\dblfloatsep 11pt plus 2pt minus 2pt % Same as \floatsep for double-column + % figures in two-column mode. +\dbltextfloatsep 18pt plus 2pt minus 4pt% \textfloatsep for double-column + % floats. +\@ifundefined{@dblmaxsep}{\newdimen\@dblmaxsep}{}% this is for LaTeX2e +\@dblmaxsep 18pt % The maximum of \dblfloatsep and + % \dbltexfloatsep. +\@fptop 0pt plus 1fil % Stretch at top of float page/column. (Must be + % 0pt plus ...) +\@fpsep 8pt plus 2fil % Space between floats on float page/column. +\@fpbot 0pt plus 1fil % Stretch at bottom of float page/column. (Must be + % 0pt plus ... ) +\@dblfptop 0pt plus 1fil % Stretch at top of float page. (Must be 0pt plus ...) +\@dblfpsep 8pt plus 2fil % Space between floats on float page. +\@dblfpbot 0pt plus 1fil % Stretch at bottom of float page. (Must be + % 0pt plus ... ) +\marginparpush 5pt % Minimum vertical separation between two marginal + % notes. + +\parskip 0pt % Extra vertical space between paragraphs. + % Set to 0pt outside sections, to keep section heads + % uniformly spaced. The value of parskip is set + % to leading value _within_ sections. + % 12 Jan 2000 gkmt +\parindent 0pt % Width of paragraph indentation. +\partopsep 2pt plus 1pt minus 1pt% Extra vertical space, in addition to + % \parskip and \topsep, added when user + % leaves blank line before environment. + +\@lowpenalty 51 % Produced by \nopagebreak[1] or \nolinebreak[1] +\@medpenalty 151 % Produced by \nopagebreak[2] or \nolinebreak[2] +\@highpenalty 301 % Produced by \nopagebreak[3] or \nolinebreak[3] + +\@beginparpenalty -\@lowpenalty % Before a list or paragraph environment. +\@endparpenalty -\@lowpenalty % After a list or paragraph environment. +\@itempenalty -\@lowpenalty % Between list items. + +\@namedef{ds at 10pt}{\@latexerr{The `10pt' option is not allowed in the `acmconf' + document style.}\@eha} +\@namedef{ds at 11pt}{\@latexerr{The `11pt' option is not allowed in the `acmconf' + document style.}\@eha} +\@namedef{ds at 12pt}{\@latexerr{The `12pt' option is not allowed in the `acmconf' + document style.}\@eha} + +\@options + +\lineskip 2pt % \lineskip is 1pt for all font sizes. +\normallineskip 2pt +\def\baselinestretch{1} + +\abovedisplayskip 9pt plus2pt minus4.5pt% +\belowdisplayskip \abovedisplayskip +\abovedisplayshortskip \z@ plus3pt% +\belowdisplayshortskip 5.4pt plus3pt minus3pt% +\let\@listi\@listI % Setting of \@listi added 9 Jun 87 + +\def\small{\@setsize\small{9pt}\viiipt\@viiipt +\abovedisplayskip 7.6pt plus 3pt minus 4pt% +\belowdisplayskip \abovedisplayskip +\abovedisplayshortskip \z@ plus2pt% +\belowdisplayshortskip 3.6pt plus2pt minus 2pt +\def\@listi{\leftmargin\leftmargini %% Added 22 Dec 87 +\topsep 4pt plus 2pt minus 2pt\parsep 2pt plus 1pt minus 1pt +\itemsep \parsep}} + +\def\footnotesize{\@setsize\footnotesize{9pt}\ixpt\@ixpt +\abovedisplayskip 6.4pt plus 2pt minus 4pt% +\belowdisplayskip \abovedisplayskip +\abovedisplayshortskip \z@ plus 1pt% +\belowdisplayshortskip 2.7pt plus 1pt minus 2pt +\def\@listi{\leftmargin\leftmargini %% Added 22 Dec 87 +\topsep 3pt plus 1pt minus 1pt\parsep 2pt plus 1pt minus 1pt +\itemsep \parsep}} + +\newcount\aucount +\newcount\originalaucount +\newdimen\auwidth +\auwidth=\textwidth +\newdimen\auskip +\newcount\auskipcount +\newdimen\auskip +\global\auskip=1pc +\newdimen\allauboxes +\allauboxes=\auwidth +\newtoks\addauthors +\newcount\addauflag +\global\addauflag=0 %Haven't shown additional authors yet + +\newtoks\subtitletext +\gdef\subtitle#1{\subtitletext={#1}} + +\gdef\additionalauthors#1{\addauthors={#1}} + +\gdef\numberofauthors#1{\global\aucount=#1 +\ifnum\aucount>3\global\originalaucount=\aucount \global\aucount=3\fi %g} +\global\auskipcount=\aucount\global\advance\auskipcount by 1 +\global\multiply\auskipcount by 2 +\global\multiply\auskip by \auskipcount +\global\advance\auwidth by -\auskip +\global\divide\auwidth by \aucount} + +% \and was modified to count the number of authors. GKMT 12 Aug 1999 +\def\alignauthor{% % \begin{tabular} +\end{tabular}% + \begin{tabular}[t]{p{\auwidth}}\centering}% + +% *** NOTE *** NOTE *** NOTE *** NOTE *** +% If you have 'font problems' then you may need +% to change these, e.g. 'arialb' instead of "arialbd". +% Gerry Murray 11/11/1999 +% *** OR ** comment out block A and activate block B or vice versa. +% ********************************************** +% +% -- Start of block A -- (Type 1 or Truetype fonts) +%\newfont{\secfnt}{timesbd at 12pt} % was timenrb originally - now is timesbd +%\newfont{\secit}{timesbi at 12pt} %13 Jan 00 gkmt +%\newfont{\subsecfnt}{timesi at 11pt} % was timenrri originally - now is timesi +%\newfont{\subsecit}{timesbi at 11pt} % 13 Jan 00 gkmt -- was times changed to timesbi gm 2/4/2000 +% % because "normal" is italic, "italic" is Roman +%\newfont{\ttlfnt}{arialbd at 18pt} % was arialb originally - now is arialbd +%\newfont{\ttlit}{arialbi at 18pt} % 13 Jan 00 gkmt +%\newfont{\subttlfnt}{arial at 14pt} % was arialr originally - now is arial +%\newfont{\subttlit}{ariali at 14pt} % 13 Jan 00 gkmt +%\newfont{\subttlbf}{arialbd at 14pt} % 13 Jan 00 gkmt +%\newfont{\aufnt}{arial at 12pt} % was arialr originally - now is arial +%\newfont{\auit}{ariali at 12pt} % 13 Jan 00 gkmt +%\newfont{\affaddr}{arial at 10pt} % was arialr originally - now is arial +%\newfont{\affaddrit}{ariali at 10pt} %13 Jan 00 gkmt +%\newfont{\eaddfnt}{arial at 12pt} % was arialr originally - now is arial +%\newfont{\ixpt}{times at 9pt} % was timenrr originally - now is times +%\newfont{\confname}{timesi at 8pt} % was timenrri - now is timesi +%\newfont{\crnotice}{times at 8pt} % was timenrr originally - now is times +%\newfont{\ninept}{times at 9pt} % was timenrr originally - now is times + +% ********************************************* +% -- End of block A -- +% +% +% -- Start of block B -- METAFONT +% +++++++++++++++++++++++++++++++++++++++++++++ +% Next (default) block for those using Metafont +% Gerry Murray 11/11/1999 +% *** THIS BLOCK FOR THOSE USING METAFONT ***** +% ********************************************* +\newfont{\secfnt}{ptmb at 12pt} +\newfont{\secit}{ptmbi at 12pt} %13 Jan 00 gkmt +\newfont{\subsecfnt}{ptmri at 11pt} +\newfont{\subsecit}{ptmbi at 11pt} % 13 Jan 00 gkmt -- was ptmr changed to ptmbi gm 2/4/2000 + % because "normal" is italic, "italic" is Roman +\newfont{\ttlfnt}{phvb at 18pt} +\newfont{\ttlit}{phvbo at 18pt} % GM 2/4/2000 +\newfont{\subttlfnt}{phvr at 14pt} +\newfont{\subttlit}{phvro at 14pt} % GM 2/4/2000 +\newfont{\subttlbf}{phvb at 14pt} % 13 Jan 00 gkmt +\newfont{\aufnt}{phvr at 12pt} +\newfont{\auit}{phvro at 12pt} % GM 2/4/2000 +\newfont{\affaddr}{phvr at 10pt} +\newfont{\affaddrit}{phvro at 10pt} % GM 2/4/2000 +\newfont{\eaddfnt}{phvr at 12pt} +\newfont{\ixpt}{ptmr at 9pt} +\newfont{\confname}{ptmri at 8pt} +\newfont{\crnotice}{ptmr at 8pt} +\newfont{\ninept}{ptmr at 9pt} +% +++++++++++++++++++++++++++++++++++++++++++++ +% -- End of block B -- + +\def\email#1{{{\eaddfnt{\vskip 4pt#1}}}} + +\def\addauthorsection{\ifnum\originalaucount>3 + \section{Additional Authors}\the\addauthors + \fi} + +\newcount\savesection +\newcount\sectioncntr +\global\sectioncntr=1 + +\setcounter{secnumdepth}{3} + +\def\appendix{\par +\section*{APPENDIX} +\setcounter{section}{0} + \setcounter{subsection}{0} + \def\thesection{\Alph{section}} } + + +\leftmargini 22.5pt +\leftmarginii 19.8pt % > \labelsep + width of '(m)' +\leftmarginiii 16.8pt % > \labelsep + width of 'vii.' +\leftmarginiv 15.3pt % > \labelsep + width of 'M.' +\leftmarginv 9pt +\leftmarginvi 9pt + +\leftmargin\leftmargini +\labelsep 4.5pt +\labelwidth\leftmargini\advance\labelwidth-\labelsep + +\def\@listI{\leftmargin\leftmargini \parsep 3.6pt plus 2pt minus 1pt% +\topsep 7.2pt plus 2pt minus 4pt% +\itemsep 3.6pt plus 2pt minus 1pt} + +\let\@listi\@listI +\@listi + +\def\@listii{\leftmargin\leftmarginii + \labelwidth\leftmarginii\advance\labelwidth-\labelsep + \topsep 3.6pt plus 2pt minus 1pt + \parsep 1.8pt plus 0.9pt minus 0.9pt + \itemsep \parsep} + +\def\@listiii{\leftmargin\leftmarginiii + \labelwidth\leftmarginiii\advance\labelwidth-\labelsep + \topsep 1.8pt plus 0.9pt minus 0.9pt + \parsep \z@ \partopsep 1pt plus 0pt minus 1pt + \itemsep \topsep} + +\def\@listiv{\leftmargin\leftmarginiv + \labelwidth\leftmarginiv\advance\labelwidth-\labelsep} + +\def\@listv{\leftmargin\leftmarginv + \labelwidth\leftmarginv\advance\labelwidth-\labelsep} + +\def\@listvi{\leftmargin\leftmarginvi + \labelwidth\leftmarginvi\advance\labelwidth-\labelsep} + +\def\labelenumi{\theenumi.} +\def\theenumi{\arabic{enumi}} + +\def\labelenumii{(\theenumii)} +\def\theenumii{\alph{enumii}} +\def\p at enumii{\theenumi} + +\def\labelenumiii{\theenumiii.} +\def\theenumiii{\roman{enumiii}} +\def\p at enumiii{\theenumi(\theenumii)} + +\def\labelenumiv{\theenumiv.} +\def\theenumiv{\Alph{enumiv}} +\def\p at enumiv{\p at enumiii\theenumiii} + +\def\labelitemi{$\bullet$} +\def\labelitemii{\bf --} +\def\labelitemiii{$\ast$} +\def\labelitemiv{$\cdot$} + +\def\verse{\let\\=\@centercr + \list{}{\itemsep\z@ \itemindent -1.5em\listparindent \itemindent + \rightmargin\leftmargin\advance\leftmargin 1.5em}\item[]} +\let\endverse\endlist + +\def\quotation{\list{}{\listparindent 1.5em + \itemindent\listparindent + \rightmargin\leftmargin \parsep 0pt plus 1pt}\item[]} +\let\endquotation=\endlist + +\def\quote{\list{}{\rightmargin\leftmargin}\item[]} +\let\endquote=\endlist + +\def\descriptionlabel#1{\hspace\labelsep \bf #1} +\def\description{\list{}{\labelwidth\z@ \itemindent-\leftmargin + \let\makelabel\descriptionlabel}} + +\let\enddescription\endlist + +\def\theequation{\arabic{equation}} + +\arraycolsep 4.5pt % Half the space between columns in an array environment. +\tabcolsep 5.4pt % Half the space between columns in a tabular environment. +\arrayrulewidth .4pt % Width of rules in array and tabular environment. +\doublerulesep 1.8pt % Space between adjacent rules in array or tabular env. + +\tabbingsep \labelsep % Space used by the \' command. (See LaTeX manual.) + +\skip\@mpfootins =\skip\footins + +\fboxsep =2.7pt % Space left between box and text by \fbox and \framebox. +\fboxrule =.4pt % Width of rules in box made by \fbox and \framebox. + +\def\thepart{\Roman{part}} % Roman numeral part numbers. +\def\thesection {\arabic{section}} +\def\thesubsection {\thesection.\arabic{subsection}} +%\def\thesubsubsection {\thesubsection.\arabic{subsubsection}} % GM 7/30/2002 +%\def\theparagraph {\thesubsubsection.\arabic{paragraph}} % GM 7/30/2002 +\def\thesubparagraph {\theparagraph.\arabic{subparagraph}} + +\def\@pnumwidth{1.55em} +\def\@tocrmarg {2.55em} +\def\@dotsep{4.5} +\setcounter{tocdepth}{3} + +\def\tableofcontents{\@latexerr{\tableofcontents: Tables of contents are not + allowed in the `acmconf' document style.}\@eha} + +\def\l at part#1#2{\addpenalty{\@secpenalty} + \addvspace{2.25em plus 1pt} % space above part line + \begingroup + \@tempdima 3em % width of box holding part number, used by + \parindent \z@ \rightskip \@pnumwidth %% \numberline + \parfillskip -\@pnumwidth + {\large \bf % set line in \large boldface + \leavevmode % TeX command to enter horizontal mode. + #1\hfil \hbox to\@pnumwidth{\hss #2}}\par + \nobreak % Never break after part entry + \endgroup} + +\def\l at section#1#2{\addpenalty{\@secpenalty} % good place for page break + \addvspace{1.0em plus 1pt} % space above toc entry + \@tempdima 1.5em % width of box holding section number + \begingroup + \parindent \z@ \rightskip \@pnumwidth + \parfillskip -\@pnumwidth + \bf % Boldface. + \leavevmode % TeX command to enter horizontal mode. + \advance\leftskip\@tempdima %% added 5 Feb 88 to conform to + \hskip -\leftskip %% 25 Jan 88 change to \numberline + #1\nobreak\hfil \nobreak\hbox to\@pnumwidth{\hss #2}\par + \endgroup} + + +\def\l at subsection{\@dottedtocline{2}{1.5em}{2.3em}} +\def\l at subsubsection{\@dottedtocline{3}{3.8em}{3.2em}} +\def\l at paragraph{\@dottedtocline{4}{7.0em}{4.1em}} +\def\l at subparagraph{\@dottedtocline{5}{10em}{5em}} + +\def\listoffigures{\@latexerr{\listoffigures: Lists of figures are not + allowed in the `acmconf' document style.}\@eha} + +\def\l at figure{\@dottedtocline{1}{1.5em}{2.3em}} + +\def\listoftables{\@latexerr{\listoftables: Lists of tables are not + allowed in the `acmconf' document style.}\@eha} +\let\l at table\l at figure + +\def\footnoterule{\kern-3\p@ + \hrule width .4\columnwidth + \kern 2.6\p@} % The \hrule has default height of .4pt . +% ------ +\long\def\@makefntext#1{\noindent +%\hbox to .5em{\hss$^{\@thefnmark}$}#1} % original +\hbox to .5em{\hss\textsuperscript{\@thefnmark}}#1} % C. Clifton / GM Oct. 2nd. 2002 +% ------- + +\long\def\@maketntext#1{\noindent +#1} + +\long\def\@maketitlenotetext#1#2{\noindent + \hbox to 1.8em{\hss$^{#1}$}#2} + +\setcounter{topnumber}{2} +\def\topfraction{.7} +\setcounter{bottomnumber}{1} +\def\bottomfraction{.3} +\setcounter{totalnumber}{3} +\def\textfraction{.2} +\def\floatpagefraction{.5} +\setcounter{dbltopnumber}{2} +\def\dbltopfraction{.7} +\def\dblfloatpagefraction{.5} + +\long\def\@makecaption#1#2{ + \vskip \baselineskip + \setbox\@tempboxa\hbox{\textbf{#1: #2}} + \ifdim \wd\@tempboxa >\hsize % IF longer than one line: + \textbf{#1: #2}\par % THEN set as ordinary paragraph. + \else % ELSE center. + \hbox to\hsize{\hfil\box\@tempboxa\hfil}\par + \fi} + +\@ifundefined{figure}{\newcounter {figure}} % this is for LaTeX2e + +\def\fps at figure{tbp} +\def\ftype at figure{1} +\def\ext at figure{lof} +\def\fnum at figure{Figure \thefigure} +\def\figure{\@float{figure}} +\let\endfigure\end at float +\@namedef{figure*}{\@dblfloat{figure}} +\@namedef{endfigure*}{\end at dblfloat} + +\@ifundefined{table}{\newcounter {table}} % this is for LaTeX2e + +\def\fps at table{tbp} +\def\ftype at table{2} +\def\ext at table{lot} +\def\fnum at table{Table \thetable} +\def\table{\@float{table}} +\let\endtable\end at float +\@namedef{table*}{\@dblfloat{table}} +\@namedef{endtable*}{\end at dblfloat} + +\newtoks\titleboxnotes +\newcount\titleboxnoteflag + +\def\maketitle{\par + \begingroup + \def\thefootnote{\fnsymbol{footnote}} + \def\@makefnmark{\hbox + to 0pt{$^{\@thefnmark}$\hss}} + \twocolumn[\@maketitle] +\@thanks + \endgroup + \setcounter{footnote}{0} + \let\maketitle\relax + \let\@maketitle\relax + \gdef\@thanks{}\gdef\@author{}\gdef\@title{}\gdef\@subtitle{}\let\thanks\relax + \@copyrightspace} + +%% CHANGES ON NEXT LINES +\newif\if at ll % to record which version of LaTeX is in use + +\expandafter\ifx\csname LaTeXe\endcsname\relax % LaTeX2.09 is used +\else% LaTeX2e is used, so set ll to true +\global\@lltrue +\fi + +\if at ll + \NeedsTeXFormat{LaTeX2e} + \ProvidesClass{acm_proc_article-sp} [2004/15/10 - V2.7SP - based on esub2acm.sty <23 April 96>] + \RequirePackage{latexsym}% QUERY: are these two really needed? + \let\dooptions\ProcessOptions +\else + \let\dooptions\@options +\fi +%% END CHANGES + +\def\@height{height} +\def\@width{width} +\def\@minus{minus} +\def\@plus{plus} +\def\hb at xt@{\hbox to} +\newif\if at faircopy +\@faircopyfalse +\def\ds at faircopy{\@faircopytrue} + +\def\ds at preprint{\@faircopyfalse} + +\@twosidetrue +\@mparswitchtrue +\def\ds at draft{\overfullrule 5\p@} +%% CHANGE ON NEXT LINE +\dooptions + +\lineskip \p@ +\normallineskip \p@ +\def\baselinestretch{1} +\def\@ptsize{0} %needed for amssymbols.sty + +%% CHANGES ON NEXT LINES +\if at ll% allow use of old-style font change commands in LaTeX2e +\@maxdepth\maxdepth +% +\DeclareOldFontCommand{\rm}{\ninept\rmfamily}{\mathrm} +\DeclareOldFontCommand{\sf}{\normalfont\sffamily}{\mathsf} +\DeclareOldFontCommand{\tt}{\normalfont\ttfamily}{\mathtt} +\DeclareOldFontCommand{\bf}{\normalfont\bfseries}{\mathbf} +\DeclareOldFontCommand{\it}{\normalfont\itshape}{\mathit} +\DeclareOldFontCommand{\sl}{\normalfont\slshape}{\@nomath\sl} +\DeclareOldFontCommand{\sc}{\normalfont\scshape}{\@nomath\sc} +\DeclareRobustCommand*{\cal}{\@fontswitch{\relax}{\mathcal}} +\DeclareRobustCommand*{\mit}{\@fontswitch{\relax}{\mathnormal}} +\fi +% +\if at ll + \renewcommand{\rmdefault}{cmr} % was 'ttm' +% Note! I have also found 'mvr' to work ESPECIALLY well. +% Gerry - October 1999 +% You may need to change your LV1times.fd file so that sc is +% mapped to cmcsc - -for smallcaps -- that is if you decide +% to change {cmr} to {times} above. (Not recommended) + \renewcommand{\@ptsize}{} + \renewcommand{\normalsize}{% + \@setfontsize\normalsize\@ixpt{10.5\p@}%\ninept% + \abovedisplayskip 6\p@ \@plus2\p@ \@minus\p@ + \belowdisplayskip \abovedisplayskip + \abovedisplayshortskip 6\p@ \@minus 3\p@ + \belowdisplayshortskip 6\p@ \@minus 3\p@ + \let\@listi\@listI + } +\else + \def\@normalsize{%changed next to 9 from 10 + \@setsize\normalsize{9\p@}\ixpt\@ixpt + \abovedisplayskip 6\p@ \@plus2\p@ \@minus\p@ + \belowdisplayskip \abovedisplayskip + \abovedisplayshortskip 6\p@ \@minus 3\p@ + \belowdisplayshortskip 6\p@ \@minus 3\p@ + \let\@listi\@listI + }% +\fi +\if at ll + \newcommand\scriptsize{\@setfontsize\scriptsize\@viipt{8\p@}} + \newcommand\tiny{\@setfontsize\tiny\@vpt{6\p@}} + \newcommand\large{\@setfontsize\large\@xiipt{14\p@}} + \newcommand\Large{\@setfontsize\Large\@xivpt{18\p@}} + \newcommand\LARGE{\@setfontsize\LARGE\@xviipt{20\p@}} + \newcommand\huge{\@setfontsize\huge\@xxpt{25\p@}} + \newcommand\Huge{\@setfontsize\Huge\@xxvpt{30\p@}} +\else + \def\scriptsize{\@setsize\scriptsize{8\p@}\viipt\@viipt} + \def\tiny{\@setsize\tiny{6\p@}\vpt\@vpt} + \def\large{\@setsize\large{14\p@}\xiipt\@xiipt} + \def\Large{\@setsize\Large{18\p@}\xivpt\@xivpt} + \def\LARGE{\@setsize\LARGE{20\p@}\xviipt\@xviipt} + \def\huge{\@setsize\huge{25\p@}\xxpt\@xxpt} + \def\Huge{\@setsize\Huge{30\p@}\xxvpt\@xxvpt} +\fi +\normalsize + +% make aubox hsize/number of authors up to 3, less gutter +% then showbox gutter showbox gutter showbox -- GKMT Aug 99 +\newbox\@acmtitlebox +\def\@maketitle{\newpage + \null + \setbox\@acmtitlebox\vbox{% +\baselineskip 20pt +\vskip 2em % Vertical space above title. + \begin{center} + {\ttlfnt \@title\par} % Title set in 18pt Helvetica (Arial) bold size. + \vskip 1.5em % Vertical space after title. +%This should be the subtitle. +{\subttlfnt \the\subtitletext\par}\vskip 1.25em%\fi + {\baselineskip 16pt\aufnt % each author set in \12 pt Arial, in a + \lineskip .5em % tabular environment + \begin{tabular}[t]{c}\@author + \end{tabular}\par} + \vskip 1.5em % Vertical space after author. + \end{center}} + \dimen0=\ht\@acmtitlebox + \advance\dimen0 by -12.75pc\relax % Increased space for title box -- KBT + \unvbox\@acmtitlebox + \ifdim\dimen0<0.0pt\relax\vskip-\dimen0\fi} + + +\newcount\titlenotecount +\global\titlenotecount=0 +\newtoks\tntoks +\newtoks\tntokstwo +\newtoks\tntoksthree +\newtoks\tntoksfour +\newtoks\tntoksfive + +\def\abstract{ +\ifnum\titlenotecount>0 % was =1 + \insert\footins{% + \reset at font\footnotesize + \interlinepenalty\interfootnotelinepenalty + \splittopskip\footnotesep + \splitmaxdepth \dp\strutbox \floatingpenalty \@MM + \hsize\columnwidth \@parboxrestore + \protected at edef\@currentlabel{% + }% + \color at begingroup +\ifnum\titlenotecount=1 + \@maketntext{% + \raisebox{4pt}{$\ast$}\rule\z@\footnotesep\ignorespaces\the\tntoks\@finalstrut\strutbox}% +\fi +\ifnum\titlenotecount=2 + \@maketntext{% + \raisebox{4pt}{$\ast$}\rule\z@\footnotesep\ignorespaces\the\tntoks\par\@finalstrut\strutbox}% +\@maketntext{% + \raisebox{4pt}{$\dagger$}\rule\z@\footnotesep\ignorespaces\the\tntokstwo\@finalstrut\strutbox}% +\fi +\ifnum\titlenotecount=3 + \@maketntext{% + \raisebox{4pt}{$\ast$}\rule\z@\footnotesep\ignorespaces\the\tntoks\par\@finalstrut\strutbox}% +\@maketntext{% + \raisebox{4pt}{$\dagger$}\rule\z@\footnotesep\ignorespaces\the\tntokstwo\par\@finalstrut\strutbox}% +\@maketntext{% + \raisebox{4pt}{$\ddagger$}\rule\z@\footnotesep\ignorespaces\the\tntoksthree\@finalstrut\strutbox}% +\fi +\ifnum\titlenotecount=4 + \@maketntext{% + \raisebox{4pt}{$\ast$}\rule\z@\footnotesep\ignorespaces\the\tntoks\par\@finalstrut\strutbox}% +\@maketntext{% + \raisebox{4pt}{$\dagger$}\rule\z@\footnotesep\ignorespaces\the\tntokstwo\par\@finalstrut\strutbox}% +\@maketntext{% + \raisebox{4pt}{$\ddagger$}\rule\z@\footnotesep\ignorespaces\the\tntoksthree\par\@finalstrut\strutbox}% +\@maketntext{% + \raisebox{4pt}{$\S$}\rule\z@\footnotesep\ignorespaces\the\tntoksfour\@finalstrut\strutbox}% +\fi +\ifnum\titlenotecount=5 + \@maketntext{% + \raisebox{4pt}{$\ast$}\rule\z@\footnotesep\ignorespaces\the\tntoks\par\@finalstrut\strutbox}% +\@maketntext{% + \raisebox{4pt}{$\dagger$}\rule\z@\footnotesep\ignorespaces\the\tntokstwo\par\@finalstrut\strutbox}% +\@maketntext{% + \raisebox{4pt}{$\ddagger$}\rule\z@\footnotesep\ignorespaces\the\tntoksthree\par\@finalstrut\strutbox}% +\@maketntext{% + \raisebox{4pt}{$\S$}\rule\z@\footnotesep\ignorespaces\the\tntoksfour\par\@finalstrut\strutbox}% +\@maketntext{% + \raisebox{4pt}{$\P$}\rule\z@\footnotesep\ignorespaces\the\tntoksfive\@finalstrut\strutbox}% +\fi + \color at endgroup} %g} +\fi +\setcounter{footnote}{0} +\section*{ABSTRACT}\normalsize %\the\parskip \the\baselineskip%\ninept +} + +\def\endabstract{\if at twocolumn\else\endquotation\fi} + +\def\keywords{\if at twocolumn +\section*{Keywords} +\else \small +\quotation +\fi} + +% I've pulled the check for 2 cols, since proceedings are _always_ +% two-column 11 Jan 2000 gkmt +\def\terms{%\if at twocolumn +\section*{General Terms} +%\else \small +%\quotation\the\parskip +%\fi} +} + +% -- Classification needs to be a bit smart due to optionals - Gerry/Georgia November 2nd. 1999 +\newcount\catcount +\global\catcount=1 + +\def\category#1#2#3{% +\ifnum\catcount=1 +\section*{Categories and Subject Descriptors} +\advance\catcount by 1\else{\unskip; }\fi + \@ifnextchar [{\@category{#1}{#2}{#3}}{\@category{#1}{#2}{#3}[]}% +} + +\def\@category#1#2#3[#4]{% + \begingroup + \let\and\relax + #1 [\textbf{#2}]% + \if!#4!% + \if!#3!\else : #3\fi + \else + :\space + \if!#3!\else #3\kern\z at ---\hskip\z@\fi + \textit{#4}% + \fi + \endgroup +} +% + +%%% This section (written by KBT) handles the 1" box in the lower left +%%% corner of the left column of the first page by creating a picture, +%%% and inserting the predefined string at the bottom (with a negative +%%% displacement to offset the space allocated for a non-existent +%%% caption). +%%% +\newtoks\copyrightnotice +\def\ftype at copyrightbox{8} +\def\@copyrightspace{ +\@float{copyrightbox}[b] +\begin{center} +\setlength{\unitlength}{1pc} +\begin{picture}(20,6) %Space for copyright notice +\put(0,-0.95){\crnotice{\@toappear}} +\end{picture} +\end{center} +\end at float} + +\def\@toappear{} % Default setting blank - commands below change this. +\long\def\toappear#1{\def\@toappear{\parbox[b]{20pc}{\baselineskip 9pt#1}}} +\def\toappearbox#1{\def\@toappear{\raisebox{5pt}{\framebox[20pc]{\parbox[b]{19pc}{#1}}}}} + +\newtoks\conf +\newtoks\confinfo +\def\conferenceinfo#1#2{\global\conf={#1}\global\confinfo{#2}} + + +\def\marginpar{\@latexerr{The \marginpar command is not allowed in the + `acmconf' document style.}\@eha} + +\mark{{}{}} % Initializes TeX's marks + +\def\today{\ifcase\month\or + January\or February\or March\or April\or May\or June\or + July\or August\or September\or October\or November\or December\fi + \space\number\day, \number\year} + +\def\@begintheorem#1#2{% + \trivlist + \item[% + \hskip 10\p@ + \hskip \labelsep + {{\sc #1}\hskip 5\p@\relax#2.}% + ] + \it +} +\def\@opargbegintheorem#1#2#3{% + \trivlist + \item[% + \hskip 10\p@ + \hskip \labelsep + {\sc #1\ #2\ % This mod by Gerry to enumerate corollaries + \setbox\@tempboxa\hbox{(#3)} % and bracket the 'corollary title' + \ifdim \wd\@tempboxa>\z@ % and retain the correct numbering of e.g. theorems + \hskip 5\p@\relax % if they occur 'around' said corollaries. + \box\@tempboxa % Gerry - Nov. 1999. + \fi.}% + ] + \it +} +\newif\if at qeded +\global\@qededfalse + +% -- original +%\def\proof{% +% \vspace{-\parskip} % GM July 2000 (for tighter spacing) +% \global\@qededfalse +% \@ifnextchar[{\@xproof}{\@proof}% +%} +% -- end of original + +% (JSS) Fix for vertical spacing bug - Gerry Murray July 30th. 2002 +\def\proof{% +\vspace{-\lastskip}\vspace{-\parsep}\penalty-51% +\global\@qededfalse +\@ifnextchar[{\@xproof}{\@proof}% +} + +\def\endproof{% + \if at qeded\else\qed\fi + \endtrivlist +} +\def\@proof{% + \trivlist + \item[% + \hskip 10\p@ + \hskip \labelsep + {\sc Proof.}% + ] + \ignorespaces +} +\def\@xproof[#1]{% + \trivlist + \item[\hskip 10\p@\hskip \labelsep{\sc Proof #1.}]% + \ignorespaces +} +\def\qed{% + \unskip + \kern 10\p@ + \begingroup + \unitlength\p@ + \linethickness{.4\p@}% + \framebox(6,6){}% + \endgroup + \global\@qededtrue +} + +\def\newdef#1#2{% + \expandafter\@ifdefinable\csname #1\endcsname + {\@definecounter{#1}% + \expandafter\xdef\csname the#1\endcsname{\@thmcounter{#1}}% + \global\@namedef{#1}{\@defthm{#1}{#2}}% + \global\@namedef{end#1}{\@endtheorem}% + }% +} +\def\@defthm#1#2{% + \refstepcounter{#1}% + \@ifnextchar[{\@ydefthm{#1}{#2}}{\@xdefthm{#1}{#2}}% +} +\def\@xdefthm#1#2{% + \@begindef{#2}{\csname the#1\endcsname}% + \ignorespaces +} +\def\@ydefthm#1#2[#3]{% + \trivlist + \item[% + \hskip 10\p@ + \hskip \labelsep + {\it #2% + \savebox\@tempboxa{#3}% + \ifdim \wd\@tempboxa>\z@ + \ \box\@tempboxa + \fi.% + }]% + \ignorespaces +} +\def\@begindef#1#2{% + \trivlist + \item[% + \hskip 10\p@ + \hskip \labelsep + {\it #1\ \rm #2.}% + ]% +} +\def\theequation{\arabic{equation}} + +\newcounter{part} +\newcounter{section} +\newcounter{subsection}[section] +\newcounter{subsubsection}[subsection] +\newcounter{paragraph}[subsubsection] +\def\thepart{\Roman{part}} +\def\thesection{\arabic{section}} +\def\thesubsection{\thesection.\arabic{subsection}} +\def\thesubsubsection{\thesubsection.\arabic{subsubsection}} %removed \subsecfnt 29 July 2002 gkmt +\def\theparagraph{\thesubsubsection.\arabic{paragraph}} %removed \subsecfnt 29 July 2002 gkmt + +\newif\if at uchead +\@ucheadfalse + +%% CHANGES: NEW NOTE +%% NOTE: OK to use old-style font commands below, since they were +%% suitably redefined for LaTeX2e +%% END CHANGES +\setcounter{secnumdepth}{3} +\def\part{% + \@startsection{part}{9}{\z@}{-10\p@ \@plus -4\p@ \@minus -2\p@} + {4\p@}{\normalsize\@ucheadtrue}% +} + +% Rationale for changes made in next four definitions: +% "Before skip" is made elastic to provide some give in setting columns (vs. +% parskip, which is non-elastic to keep section headers "anchored" to their +% subsequent text. +% +% "After skip" is minimized -- BUT setting it to 0pt resulted in run-in heads, despite +% the documentation asserted only after-skip < 0pt would have result. +% +% Baselineskip added to style to ensure multi-line section titles, and section heads +% followed by another section head rather than text, are decently spaced vertically. +% 12 Jan 2000 gkmt +\def\section{% + \@startsection{section}{1}{\z@}{-10\p@ \@plus -4\p@ \@minus -2\p@}% + {0.5pt}{\baselineskip=14pt\secfnt\@ucheadtrue}% +} + +\def\subsection{% + \@startsection{subsection}{2}{\z@}{-10\p@ \@plus -4\p@ \@minus -2\p@} + {0.5pt}{\baselineskip=14pt\secfnt}% +} +\def\subsubsection{% + \@startsection{subsubsection}{3}{\z@}{-10\p@ \@plus -4\p@ \@minus -2\p@}% + {0.5pt}{\baselineskip=14pt\subsecfnt}% +} + +\def\paragraph{% + \@startsection{paragraph}{3}{\z@}{-10\p@ \@plus -4\p@ \@minus -2\p@}% + {0.5pt}{\baselineskip=14pt\subsecfnt}% +} + +\let\@period=. +\def\@startsection#1#2#3#4#5#6{% + \if at noskipsec %gkmt, 11 aug 99 + \global\let\@period\@empty + \leavevmode + \global\let\@period.% + \fi + \par + \@tempskipa #4\relax + \@afterindenttrue + \ifdim \@tempskipa <\z@ + \@tempskipa -\@tempskipa + \@afterindentfalse + \fi + %\if at nobreak 11 Jan 00 gkmt + %\everypar{} + %\else + \addpenalty\@secpenalty + \addvspace\@tempskipa + %\fi + \parskip=0pt + \@ifstar + {\@ssect{#3}{#4}{#5}{#6}} + {\@dblarg{\@sect{#1}{#2}{#3}{#4}{#5}{#6}}}% +} + + +\def\@ssect#1#2#3#4#5{% + \@tempskipa #3\relax + \ifdim \@tempskipa>\z@ + \begingroup + #4{% + \@hangfrom{\hskip #1}% + \interlinepenalty \@M #5\@@par}% + \endgroup + \else + \def\@svsechd{#4{\hskip #1\relax #5}}% + \fi + \vskip -10.5pt %gkmt, 7 jan 00 -- had been -14pt, now set to parskip + \@xsect{#3}\parskip=10.5pt} % within the starred section, parskip = leading 12 Jan 2000 gkmt + + +\def\@sect#1#2#3#4#5#6[#7]#8{% + \ifnum #2>\c at secnumdepth + \let\@svsec\@empty + \else + \refstepcounter{#1}% + \edef\@svsec{% + \begingroup + %\ifnum#2>2 \noexpand\rm \fi % changed to next 29 July 2002 gkmt + \ifnum#2>2 \noexpand#6 \fi + \csname the#1\endcsname + \endgroup + \ifnum #2=1\relax .\fi + \hskip 1em + }% + \fi + \@tempskipa #5\relax + \ifdim \@tempskipa>\z@ + \begingroup + #6\relax + \@hangfrom{\hskip #3\relax\@svsec}% + \begingroup + \interlinepenalty \@M + \if at uchead + \uppercase{#8}% + \else + #8% + \fi + \par + \endgroup + \endgroup + \csname #1mark\endcsname{#7}% + \vskip -10.5pt % -14pt gkmt, 11 aug 99 -- changed to -\parskip 11 Jan 2000 + \addcontentsline{toc}{#1}{% + \ifnum #2>\c at secnumdepth \else + \protect\numberline{\csname the#1\endcsname}% + \fi + #7% + }% + \else + \def\@svsechd{% + #6% + \hskip #3\relax + \@svsec + \if at uchead + \uppercase{#8}% + \else + #8% + \fi + \csname #1mark\endcsname{#7}% + \addcontentsline{toc}{#1}{% + \ifnum #2>\c at secnumdepth \else + \protect\numberline{\csname the#1\endcsname}% + \fi + #7% + }% + }% + \fi + \@xsect{#5}\parskip=10.5pt% within the section, parskip = leading 12 Jan 2000 gkmt +} +\def\@xsect#1{% + \@tempskipa #1\relax + \ifdim \@tempskipa>\z@ + \par + \nobreak + \vskip \@tempskipa + \@afterheading + \else + \global\@nobreakfalse + \global\@noskipsectrue + \everypar{% + \if at noskipsec + \global\@noskipsecfalse + \clubpenalty\@M + \hskip -\parindent + \begingroup + \@svsechd + \@period + \endgroup + \unskip + \@tempskipa #1\relax + \hskip -\@tempskipa + \else + \clubpenalty \@clubpenalty + \everypar{}% + \fi + }% + \fi + \ignorespaces +} + +\def\@trivlist{% + \@topsepadd\topsep + \if at noskipsec + \global\let\@period\@empty + \leavevmode + \global\let\@period.% + \fi + \ifvmode + \advance\@topsepadd\partopsep + \else + \unskip + \par + \fi + \if at inlabel + \@noparitemtrue + \@noparlisttrue + \else + \@noparlistfalse + \@topsep\@topsepadd + \fi + \advance\@topsep \parskip + \leftskip\z at skip + \rightskip\@rightskip + \parfillskip\@flushglue + \@setpar{\if at newlist\else{\@@par}\fi} + \global\@newlisttrue + \@outerparskip\parskip +} + +%%% Actually, 'abbrev' works just fine as the default - Gerry Feb. 2000 +%%% Bibliography style. + +\parindent 0pt +\typeout{Using 'Abbrev' bibliography style} +\newcommand\bibyear[2]{% + \unskip\quad\ignorespaces#1\unskip + \if#2..\quad \else \quad#2 \fi +} +\newcommand{\bibemph}[1]{{\em#1}} +\newcommand{\bibemphic}[1]{{\em#1\/}} +\newcommand{\bibsc}[1]{{\sc#1}} +\def\@normalcite{% + \def\@cite##1##2{[##1\if at tempswa , ##2\fi]}% +} +\def\@citeNB{% + \def\@cite##1##2{##1\if at tempswa , ##2\fi}% +} +\def\@citeRB{% + \def\@cite##1##2{##1\if at tempswa , ##2\fi]}% +} +\def\start at cite#1#2{% + \edef\citeauthoryear##1##2##3{% + ###1% + \ifnum#2=\z@ \else\ ###2\fi + }% + \ifnum#1=\thr@@ + \let\@@cite\@citeyear + \else + \let\@@cite\@citenormal + \fi + \@ifstar{\@citeNB\@@cite}{\@normalcite\@@cite}% +} +\def\cite{\start at cite23} +\def\citeNP{\cite*} +\def\citeA{\start at cite10} +\def\citeANP{\citeA*} +\def\shortcite{\start at cite23} +\def\shortciteNP{\shortcite*} +\def\shortciteA{\start at cite20} +\def\shortciteANP{\shortciteA*} +\def\citeyear{\start at cite30} +\def\citeyearNP{\citeyear*} +\def\citeN{% + \@citeRB + \def\citeauthoryear##1##2##3{##1\ [##3% + \def\reserved at a{##1}% + \def\citeauthoryear####1####2####3{% + \def\reserved at b{####1}% + \ifx\reserved at a\reserved at b + ####3% + \else + \errmessage{Package acmart Error: author mismatch + in \string\citeN^^J^^J% + See the acmart package documentation for explanation}% + \fi + }% + }% + \@ifstar\@citeyear\@citeyear +} +\def\shortciteN{% + \@citeRB + \def\citeauthoryear##1##2##3{##2\ [##3% + \def\reserved at a{##2}% + \def\citeauthoryear####1####2####3{% + \def\reserved at b{####2}% + \ifx\reserved at a\reserved at b + ####3% + \else + \errmessage{Package acmart Error: author mismatch + in \string\shortciteN^^J^^J% + See the acmart package documentation for explanation}% + \fi + }% + }% + \@ifstar\@citeyear\@citeyear % changed from "\@ifstart" 12 Jan 2000 gkmt +} + +\def\@citenormal{% + \@ifnextchar [{\@tempswatrue\@citex;} + {\@tempswafalse\@citex,[]}% was ; Gerry 2/24/00 +} +\def\@citeyear{% + \@ifnextchar [{\@tempswatrue\@citex,}% + {\@tempswafalse\@citex,[]}% +} +\def\@citex#1[#2]#3{% + \let\@citea\@empty + \@cite{% + \@for\@citeb:=#3\do{% + \@citea + \def\@citea{#1 }% + \edef\@citeb{\expandafter\@iden\@citeb}% + \if at filesw + \immediate\write\@auxout{\string\citation{\@citeb}}% + \fi + \@ifundefined{b@\@citeb}{% + {\bf ?}% + \@warning{% + Citation `\@citeb' on page \thepage\space undefined% + }% + }% + {\csname b@\@citeb\endcsname}% + }% + }{#2}% +} +\let\@biblabel\@gobble +\newdimen\bibindent +\setcounter{enumi}{1} +\bibindent=0em +\def\thebibliography#1{% +\ifnum\addauflag=0\addauthorsection\global\addauflag=1\fi + \section{% + {References} % was uppercased but this affects pdf bookmarks (SP/GM Oct. 2004) + \@mkboth{{\refname}}{{\refname}}% + }% + \list{[\arabic{enumi}]}{% + \settowidth\labelwidth{[#1]}% + \leftmargin\labelwidth + \advance\leftmargin\labelsep + \advance\leftmargin\bibindent + \itemindent -\bibindent + \listparindent \itemindent + \usecounter{enumi} + }% + \let\newblock\@empty + \raggedright %% 7 JAN 2000 gkmt + \sloppy + \sfcode`\.=1000\relax +} + + +\gdef\balancecolumns +{\vfill\eject +\global\@colht=\textheight +\global\ht\@cclv=\textheight +} + +\newcount\colcntr +\global\colcntr=0 +\newbox\savebox + +\gdef \@makecol {% +\global\advance\colcntr by 1 +\ifnum\colcntr>2 \global\colcntr=1\fi + \ifvoid\footins + \setbox\@outputbox \box\@cclv + \else + \setbox\@outputbox \vbox{% +\boxmaxdepth \@maxdepth + \@tempdima\dp\@cclv + \unvbox \@cclv + \vskip-\@tempdima + \vskip \skip\footins + \color at begingroup + \normalcolor + \footnoterule + \unvbox \footins + \color at endgroup + }% + \fi + \xdef\@freelist{\@freelist\@midlist}% + \global \let \@midlist \@empty + \@combinefloats + \ifvbox\@kludgeins + \@makespecialcolbox + \else + \setbox\@outputbox \vbox to\@colht {% +\@texttop + \dimen@ \dp\@outputbox + \unvbox \@outputbox + \vskip -\dimen@ + \@textbottom + }% + \fi + \global \maxdepth \@maxdepth +} +\def\titlenote{\@ifnextchar[\@xtitlenote{\stepcounter\@mpfn +\global\advance\titlenotecount by 1 +\ifnum\titlenotecount=1 + \raisebox{9pt}{$\ast$} +\fi +\ifnum\titlenotecount=2 + \raisebox{9pt}{$\dagger$} +\fi +\ifnum\titlenotecount=3 + \raisebox{9pt}{$\ddagger$} +\fi +\ifnum\titlenotecount=4 +\raisebox{9pt}{$\S$} +\fi +\ifnum\titlenotecount=5 +\raisebox{9pt}{$\P$} +\fi + \@titlenotetext +}} + +\long\def\@titlenotetext#1{\insert\footins{% +\ifnum\titlenotecount=1\global\tntoks={#1}\fi +\ifnum\titlenotecount=2\global\tntokstwo={#1}\fi +\ifnum\titlenotecount=3\global\tntoksthree={#1}\fi +\ifnum\titlenotecount=4\global\tntoksfour={#1}\fi +\ifnum\titlenotecount=5\global\tntoksfive={#1}\fi + \reset at font\footnotesize + \interlinepenalty\interfootnotelinepenalty + \splittopskip\footnotesep + \splitmaxdepth \dp\strutbox \floatingpenalty \@MM + \hsize\columnwidth \@parboxrestore + \protected at edef\@currentlabel{% + }% + \color at begingroup + \color at endgroup}} + +%%%%%%%%%%%%%%%%%%%%%%%%% +\ps at plain +\baselineskip=11pt +\let\thepage\relax % For NO page numbers - Gerry Nov. 30th. 1999 +\def\setpagenumber#1{\global\setcounter{page}{#1}} +%\pagenumbering{arabic} % Arabic page numbers but commented out for NO page numbes - Gerry Nov. 30th. 1999 +\twocolumn % Double column. +\flushbottom % Even bottom -- alas, does not balance columns at end of document +\pagestyle{plain} + +% Need Copyright Year and Copyright Data to be user definable (in .tex file). +% Gerry Nov. 30th. 1999 +\newtoks\copyrtyr +\newtoks\acmcopyr +\newtoks\boilerplate +\def\CopyrightYear#1{\global\copyrtyr{#1}} +\def\crdata#1{\global\acmcopyr{#1}} +\def\permission#1{\global\boilerplate{#1}} +% +\newtoks\copyrightetc +\global\copyrightetc{\ } % Need to have 'something' so that adequate space is left for pasting in a line if "confinfo" is supplied. + +\toappear{\the\boilerplate\par +{\confname{\the\conf}} \the\confinfo\par \the\copyrightetc} +% End of ACM_PROC_ARTICLE-SP.CLS -- V2.7SP - 10/15/2004 -- +% Gerry Murray -- October 15th. 2004 From tismer at codespeak.net Tue May 30 18:03:04 2006 From: tismer at codespeak.net (tismer at codespeak.net) Date: Tue, 30 May 2006 18:03:04 +0200 (CEST) Subject: [pypy-svn] r27924 - pypy/dist/pypy/module/stackless/test Message-ID: <20060530160304.D3D0510057@code0.codespeak.net> Author: tismer Date: Tue May 30 18:03:03 2006 New Revision: 27924 Modified: pypy/dist/pypy/module/stackless/test/stackless_.py Log: small cosmetic changes, some addition to the docs Modified: pypy/dist/pypy/module/stackless/test/stackless_.py ============================================================================== --- pypy/dist/pypy/module/stackless/test/stackless_.py (original) +++ pypy/dist/pypy/module/stackless/test/stackless_.py Tue May 30 18:03:03 2006 @@ -140,7 +140,7 @@ Example: def channel_cb(channel, tasklet, sending, willblock): ... - sending and willblock are integers. + sending and willblock are booleans. Pass None to switch monitoring off again. """ pass @@ -151,7 +151,8 @@ def set_schedule_callback(callable): """ set_schedule_callback(callable) -- install a callback for scheduling. - Every explicit or implicit schedule will call the callback function. + Every explicit or implicit schedule will call the callback function + right before the switch is actually done. Example: def schedule_cb(prev, next): ... @@ -302,27 +303,27 @@ Tasklet Flag Definition ----------------------- - blocked: The tasklet is either waiting in a channel for - writing (1) or reading (-1) or not blocked (0). - Maintained by the channel logic. Do not change. + blocked: The tasklet is either waiting in a channel for + writing (1) or reading (-1) or not blocked (0). + Maintained by the channel logic. Do not change. - atomic: If true, schedulers will never switch. Driven by - the code object or dynamically, see below. + atomic: If true, schedulers will never switch. Driven by + the code object or dynamically, see below. ignore_nesting: Allows auto-scheduling, even if nesting_level - is not zero. + is not zero. autoschedule: The tasklet likes to be auto-scheduled. User driven. block_trap: Debugging aid. Whenever the tasklet would be - blocked by a channel, an exception is raised. + blocked by a channel, an exception is raised. - is_zombie: This tasklet is almost dead, its deallocation has - started. The tasklet *must* die at some time, or the - process can never end. + is_zombie: This tasklet is almost dead, its deallocation has + started. The tasklet *must* die at some time, or the + process can never end. pending_irq: If set, an interrupt was issued during an atomic - operation, and should be handled when possible. + operation, and should be handled when possible. Policy for atomic/autoschedule and switching: @@ -332,13 +333,13 @@ atomic autoschedule - 1 any Neither a scheduler nor a watchdog will - try to switch this tasklet. + 1 any Neither a scheduler nor a watchdog will + try to switch this tasklet. - 0 0 The tasklet can be stopped on desire, or it - can be killed by an exception. + 0 0 The tasklet can be stopped on desire, or it + can be killed by an exception. - 0 1 Like above, plus auto-scheduling is enabled. + 0 1 Like above, plus auto-scheduling is enabled. Default settings: ----------------- @@ -484,7 +485,7 @@ pass ## note: see above - def set_ignore_nesting(self,flag): + def set_ignore_nesting(self, flag): """ t.set_ignore_nesting(flag) -- set tasklet ignore_nesting status and return current one. If set, the tasklet may be be auto-scheduled, @@ -502,7 +503,7 @@ ## tasklet(func)(*args, **kwds) ## is identical to ## t = tasklet; t.bind(func); t.setup(*args, **kwds) - def setup(self,*argl,**argd): + def setup(self, *argl, **argd): """ supply the parameters for the callable """ @@ -520,13 +521,13 @@ closing: When the closing flag is set, the channel does not - accept to be extended. The computed attribute - 'closed' is true when closing is set and the - channel is empty. - - preference: 0 no preference, caller will continue - 1 sender will be inserted after receiver and run - -1 receiver will be inserted after sender and run + accept to be extended. The computed attribute + 'closed' is true when closing is set and the + channel is empty. + + preference: 0 no preference, caller will continue + 1 sender will be inserted after receiver and run + -1 receiver will be inserted after sender and run schedule_all: ignore preference and always schedule the next task From arigo at codespeak.net Tue May 30 18:13:20 2006 From: arigo at codespeak.net (arigo at codespeak.net) Date: Tue, 30 May 2006 18:13:20 +0200 (CEST) Subject: [pypy-svn] r27925 - pypy/extradoc/talk/dls2006 Message-ID: <20060530161320.B80A610036@code0.codespeak.net> Author: arigo Date: Tue May 30 18:13:19 2006 New Revision: 27925 Modified: pypy/extradoc/talk/dls2006/draft.txt Log: Conclusion. Modified: pypy/extradoc/talk/dls2006/draft.txt ============================================================================== --- pypy/extradoc/talk/dls2006/draft.txt (original) +++ pypy/extradoc/talk/dls2006/draft.txt Tue May 30 18:13:19 2006 @@ -1142,18 +1142,41 @@ ============================================================ -XXX - -nice interpreter not polluted by implementation details -here Python, but any interpreter works - -architecture allows implementing features at the right level - -dynamic language enables defining our own various type systems -[ref pluggable type systems] - -practical VMs will result with a bit more efforts - +The PyPy project aims at showing that dynamic languages are suitable and +quite useful for writing virtual machines in. We believe that we have +achieved this objective. The present paper gave an overview of the +architecture that enabled this result. Experiments suggest that +practical virtual machines could reasonably follow in the near future, +with faster-than-current virtual machines with JIT specialization +techniques for the mid-term future. + +Targetting platforms that are very different from C/Posix is work in +progress, but given that many of the initial components are shared with +the existing stack of transformations leading to C, we are confident +that this work will soon give results. Moreover, we believe that these +results will show a reasonable efficiency, because the back-ends for VMs +like Squeak and .NET can take advantage of high-level input (as opposed +to trying to translate, say, C-like code to Smalltalk). + +A desirable property of our approach is to allow a given language and VM +to be specified only once, in the form of an interpreter. Moreover, the +interpreter can be kept simple (and thus keep its role as a +specification): not only is it written in a high-level language, but it +is not overloaded with low-level design choices and implementation +details. This makes language evolution and experimentation easier. +More generally, this property is important because many interpreters for +very difference languages can be written: the simpler these interpreters +can be kept, the more we win from our investment in writing the +tool-chain itself - a one-time effort. + +Dynamic languages enable the definition of multiple custom type systems, +similar to *pluggable type systems* in Bracha_. This proved a key +feature in implementing our translation tool-chain, because it makes a +many-levels approach convenient: each abstraction level can provide an +implementation for some of the features that the higher levels +considered primitive. It offsets the need to define a minimal kernel of +primitives and build everything on top of it; instead, we have been able +to implement, so to speak, the right feature at the right level. References @@ -1177,6 +1200,7 @@ .. _`[PE]`: XXX .. _`[BTA]`: XXX .. _Psyco: XXX +.. _Bracha: XXX .. http://www.cs.jhu.edu/~scott/pll/constraints.html page to the reference /recent result for constraint-based type inference From pedronis at codespeak.net Tue May 30 18:18:21 2006 From: pedronis at codespeak.net (pedronis at codespeak.net) Date: Tue, 30 May 2006 18:18:21 +0200 (CEST) Subject: [pypy-svn] r27926 - pypy/extradoc/talk/dls2006 Message-ID: <20060530161821.685B710057@code0.codespeak.net> Author: pedronis Date: Tue May 30 18:18:20 2006 New Revision: 27926 Added: pypy/extradoc/talk/dls2006/draft.bib (contents, props changed) Log: start of a bib file of the references Added: pypy/extradoc/talk/dls2006/draft.bib ============================================================================== --- (empty file) +++ pypy/extradoc/talk/dls2006/draft.bib Tue May 30 18:18:20 2006 @@ -0,0 +1,160 @@ + at inproceedings{PlugType, % fix + author = {Bracha, Gilad }, + journal = {Workshop on Revival of Dynamic Languages}, + keywords = {language-implementation}, + month = {October}, + priority = {2}, + title = {Pluggable Type Systems}, + year = {2004} +} + +% Hindley-Milner + at inproceedings{582176, + author = {Luis Damas and Robin Milner}, + title = {Principal type-schemes for functional programs}, + booktitle = {POPL '82: Proceedings of the 9th ACM SIGPLAN-SIGACT symposium on Principles of programming languages}, + year = {1982}, + isbn = {0-89791-065-6}, + pages = {207--212}, + location = {Albuquerque, Mexico}, + doi = {http://doi.acm.org/10.1145/582153.582176}, + publisher = {ACM Press}, + address = {New York, NY, USA}, + } + + at article{DBLP:journals/jcss/Milner78, + author = {Robin Milner}, + title = {A Theory of Type Polymorphism in Programming.}, + journal = {J. Comput. Syst. Sci.}, + volume = {17}, + number = {3}, + year = {1978}, + pages = {348-375}, + bibsource = {DBLP, http://dblp.uni-trier.de} +} + +% SSA/SSI + at mastersthesis{SSI, + author = {C. S. Ananian}, + title = {The static single information form.} + school = { Massachusetts Institute of Technology} + year = {1999} + month = {September} +} + + at article{SSA, + author = "Ron Cytron and Jeanne Ferrante and Barry K. Rosen and Mark N. Wegman and F. Kenneth Zadeck", + title = "Efficiently Computing Static Single Assignment Form and the Control Dependence Graph", + journal = "ACM Transactions on Programming Languages and Systems", + volume = "13", + number = "4", + month = "October", + publisher = "ACM Press", + pages = "451--490", + year = "1991" } + +% Squeak/ PreScheme + at inproceedings{Squeak, + author = {Dan Ingalls and Ted Kaehler and John Maloney and Scott Wallace and Alan Kay}, + title = {Back to the future: the story of Squeak, a practical Smalltalk written in itself}, + booktitle = {OOPSLA '97: Proceedings of the 12th ACM SIGPLAN conference on Object-oriented programming, systems, languages, and applications}, + year = {1997}, + isbn = {0-89791-908-4}, + pages = {318--326}, + location = {Atlanta, Georgia, United States}, + doi = {http://doi.acm.org/10.1145/263698.263754}, + publisher = {ACM Press}, + address = {New York, NY, USA}, + } + + at misc{ kelsey-prescheme, + author = "R. Kelsey", + title = "Pre-Scheme: A Scheme Dialect for Systems Programming", + text = "Richard Kelsey. Pre-Scheme: A Scheme Dialect for Systems Programming. ?." } + +% Psyco + at inproceedings{1014010, + author = {Armin Rigo}, + title = {Representation-based just-in-time specialization and the psyco prototype for python}, + booktitle = {PEPM '04: Proceedings of the 2004 ACM SIGPLAN symposium on Partial evaluation and semantics-based program manipulation}, + year = {2004}, + isbn = {1-58113-835-0}, + pages = {15--26}, + location = {Verona, Italy}, + doi = {http://doi.acm.org/10.1145/1014007.1014010}, + publisher = {ACM Press}, + address = {New York, NY, USA}, + } + +% Jikes + at inproceedings{Jikes-GC, + author = {Stephen M. Blackburn and + Perry Cheng and + Kathryn S. McKinley}, + title = {Oil and Water? High Performance Garbage Collection in Java + with MMTk.}, + booktitle = {ICSE}, + year = {2004}, + pages = {137-146}, + ee = {http://csdl.computer.org/comp/proceedings/icse/2004/2163/00/21630137abs.htm}, + crossref = {DBLP:conf/icse/2004}, + bibsource = {DBLP, http://dblp.uni-trier.de} +} + +% old overview paper + at article{DBLP:journals/ibmsj/AlpernABBCCCFGHHLLMNRSSSSSSW00, + author = {Bowen Alpern and + C. Richard Attanasio and + John J. Barton and + Michael G. Burke and + Perry Cheng and + Jong-Deok Choi and + Anthony Cocchi and + Stephen J. Fink and + David Grove and + Michael Hind and + Susan Flynn Hummel and + Derek Lieber and + Vassily Litvinov and + Mark F. Mergen and + Ton Ngo and + James R. Russell and + Vivek Sarkar and + Mauricio J. Serrano and + Janice C. Shepherd and + Stephen E. Smith and + Vugranam C. Sreedhar and + Harini Srinivasan and + John Whaley}, + title = {The Jalapeo virtual machine.}, + journal = {IBM Systems Journal}, + volume = {39}, + number = {1}, + year = {2000}, + pages = {211-}, + ee = {http://www.research.ibm.com/journal/sj/391/alpern.html}, + bibsource = {DBLP, http://dblp.uni-trier.de} +} + +% Jikes jit, more recent techreport + at techreport{Jikes-JIT, + title = {Architecture and Policy for Adaptive Optimization in Virtual Machines}, + author = {Matthew Arnold, Stephen Fink, David Grove, Michael Hind, and Peter F. Sweeney}, + year = 2004, + institution = {IBM Research}, + number = 23429, + month = "November", +} + +% constraint-based type inference + at inproceedings{679874, + author = {Tiejun Wang and Scott F. Smith}, + title = {Precise Constraint-Based Type Inference for Java}, + booktitle = {ECOOP '01: Proceedings of the 15th European Conference on Object-Oriented Programming}, + year = {2001}, + isbn = {3-540-42206-4}, + pages = {99--117}, + publisher = {Springer-Verlag}, + address = {London, UK}, + } + From ale at codespeak.net Tue May 30 18:21:20 2006 From: ale at codespeak.net (ale at codespeak.net) Date: Tue, 30 May 2006 18:21:20 +0200 (CEST) Subject: [pypy-svn] r27927 - pypy/dist/pypy/lib/pyontology Message-ID: <20060530162120.58AF31005A@code0.codespeak.net> Author: ale Date: Tue May 30 18:21:19 2006 New Revision: 27927 Modified: pypy/dist/pypy/lib/pyontology/constraint_classes.py pypy/dist/pypy/lib/pyontology/pyontology.py Log: Major rewrite in progress../test/test_ontology.py Modified: pypy/dist/pypy/lib/pyontology/constraint_classes.py ============================================================================== --- pypy/dist/pypy/lib/pyontology/constraint_classes.py (original) +++ pypy/dist/pypy/lib/pyontology/constraint_classes.py Tue May 30 18:21:19 2006 @@ -24,22 +24,32 @@ card = 0 return card +import py +from pypy.tool.ansi_print import ansi_log +log = py.log.Producer("CardinalityConstraint") +py.log.setconsumer("CardinalityConstraint", ansi_log) + class CardinalityConstraint(AbstractConstraint): cost = 10 def __init__(self, prop, restr, var, comp): - AbstractConstraint.__init__(self, [prop]) - self.check_individual = "domains['%s'].getValues() != []" % prop - self.formula = "len(domains['%s'].getValuesPrKey('%s')) %s int(%s)"% (prop, restr, comp, var) + AbstractConstraint.__init__(self, [restr]) + self.prop = prop + self.formula = "lambda x,y:len(x.getValuesPrKey(y)) %s int(%s)"% (comp, var) def estimateCost(self, domains): return self.cost def narrow(self, domains): - if eval(self.check_individual): - if not eval(self.formula): - raise ConsistencyFailure + log(self.formula) + + if domains[self.prop].getValues() != []: + log ("%r"% self._variables[0]) + for indi in domains[self._variables[0]].getValues(): + log("%s" % indi) + if not eval(self.formula)(domains[self.prop],indi): + raise ConsistencyFailure class NothingConstraint(AbstractConstraint): @@ -206,11 +216,10 @@ domain = domains[self.variable].getValues() vals = {} for cls, val in domain: - for v in val: - if vals.has_key(v): - raise ConsistencyFailure("InverseFunctionalCardinality error") - else: - vals[v] = 1 + if vals.has_key(val): + raise ConsistencyFailure("InverseFunctionalCardinality error") + else: + vals[val] = 1 else: return 0 @@ -459,10 +468,11 @@ class HasvalueConstraint(AbstractConstraint): - def __init__(self, variable, List): + def __init__(self, variable, property, value): AbstractConstraint.__init__(self, [variable]) self.variable = variable - self.List = List + self.property = property + self.value = value cost = 100 @@ -470,15 +480,15 @@ return self.cost def narrow(self, domains): - val = self.List - property = domains[self.variable].property - cls = domains[self.variable].getValues()[0] - prop = Linkeddict(domains[property].getValues()) - for v in prop[cls]: + """ This is to check the assertion that the class self.variable has a value of self.value + for the property """ + val = self.value + prop = domains[self.property].getValuesPrKey(self.variable) + for v in prop: if v == val: break else: raise ConsistencyFailure( "The value of the property %s in the class %s has a value not from %r" - %(property, cls, val)) + %(self.property, self.variable, self.value)) Modified: pypy/dist/pypy/lib/pyontology/pyontology.py ============================================================================== --- pypy/dist/pypy/lib/pyontology/pyontology.py (original) +++ pypy/dist/pypy/lib/pyontology/pyontology.py Tue May 30 18:21:19 2006 @@ -30,6 +30,8 @@ rdf_first = URIRef(u'http://www.w3.org/1999/02/22-rdf-syntax-ns#first') rdf_nil = URIRef(u'http://www.w3.org/1999/02/22-rdf-syntax-ns#nil') + + def getUriref(ns, obj): return URIRef(namespaces[ns]+'#'+obj) @@ -46,7 +48,7 @@ format = "n3" return format -class ClassDomain(AbstractDomain): +class ClassDomain(fd, object): # Class domain is intended as a (abstract/virtual) domain for implementing # Class axioms. Working on class descriptions the class domain should allow @@ -57,50 +59,82 @@ def __init__(self, name='', values=[], bases = []): AbstractDomain.__init__(self) - self.bases = bases+[self] + self.name = name self.values = {} self.setValues(values) - self.name = name self.property = None - # The TBox is a dictionary containing terminology constraints - # on predicates for this class. Keys are predicates, constraint - # tupples ie. (p,'Carddinality') and values are list, comparison - # tupples - self.TBox = {} - # The ABox contains the constraints the individuals of the class - # shall comply to - self.ABox = {} - + self.constraint = [] + self.un_constraint = [] + self.in_constraint = [] + self.domains = {} + self._bases = [] #bases #+[name] + self.finished = False + + def finish(self, variables, glob_constraints): + # The finish method constructs the constraints + if not self.finished: + log("FINISH %s" % self.name) + # Try to initialise constraints for this class + for constraint in self.un_constraint: + dom, constraints = constraint(self.name, variables[self.property], self.value) + if dom: + self.domains.update(dom) + self.in_constraint.extend(constraints) + # Initialise constraints from the base classes + for cls in self.bases: + cls = variables[cls] + dom,constraint = cls.finish(variables, glob_constraints) + # if the base class is a Restriction we shouldnt add the constraints to the store + if not isinstance(cls, Restriction): + self.domains.update(dom) + self.constraint.extend(constraint) + # initialise the constraint with this class as the first argument + for constraint in cls.un_constraint: + dom, constraints = constraint(self.name, variables[cls.property], cls.value) + self.domains.update(dom) + log("Updating constraints %r" % constraints) + self.in_constraint.extend(constraints) + self.finished = True + log("RESULT of finish %r, %r" %(self.domains,self.in_constraint)) + # update the store + if 'owl_Thing' in variables.keys() and isinstance(self, ClassDomain): + variables[self.name].setValues(variables['owl_Thing'].getValues()) + variables.update(self.domains) + glob_constraints.extend(self.in_constraint) + assert len([x for x in glob_constraints if type(x)==list])==0 + return self.domains, self.un_constraint + def __repr__(self): - return "<%s %s %r>" % (self.__class__, str(self.name),self.getValues()) - - def __getitem__(self, index): - return None - - def __iter__(self): - return iter(self.bases) - - def size(self): - return len(self.bases) - - __len__ = size + return "<%s %s %r>" % (self.__class__, str(self.name), self.getValues()) def copy(self): return self + def size(self): + return len(self.getValues()) + def removeValues(self, values): for val in values: - self.values.pop(self.values.index(val)) + self.values.pop(val) #(self.values.index(val)) def getBases(self): - return self.bases + return self._bases + def setBases(self, bases): + log(">>>>>>>>>>>>>>>>>>>>>>> %r" %self.name) + assert self.name != 'owl_Class' + self._bases = bases + bases = property(getBases, setBases) + def addValue(self, value): self.values[value] = True def getValues(self): return self.values.keys() - + + def __iter__(self): + return iter(self.values.keys()) + def setValues(self, values): self.values = dict.fromkeys(values) @@ -113,17 +147,28 @@ ClassDomain.__init__(self, name, values, bases) # self.constraint = ListConstraint(name) -class Property(Thing): +class Property(fd): # Property contains the relationship between a class instance and a value # - a pair. To accomodate global assertions like 'range' and 'domain' attributes # for range and domain must be filled in by rdfs:range and rdfs:domain def __init__(self, name='', values=[], bases = []): - ClassDomain.__init__(self, name, values, bases) + AbstractDomain.__init__(self) + self.name = name self._dict = {} self.range = [] self.domain = [] + self.property = None + self.constraint = [] + self.un_constraint = [] + self.in_constraint = [] + + def finish(self, var, constraints): + return var, constraints + def size(self): + return len(self.getValues()) + def getValues(self): items = self._dict.items() res = [] @@ -134,7 +179,7 @@ def getValuesPrKey(self, key= None): if key: - return self._dict[key] + return self._dict.get(key,[]) return self._dict.items() def addValue(self, key, val): @@ -180,13 +225,13 @@ def __init__(self, name='', values=[], bases = []): ClassDomain.__init__(self, name, values, bases) - self.constraint = NothingConstraint(name) + self.constraint = [NothingConstraint(name)] class FunctionalProperty(Property): def __init__(self, name='', values=[], bases = []): Property.__init__(self, name, values, bases) - self.constraint = FunctionalCardinality(name) + self.constraint = [FunctionalCardinality(name)] def addValue(self, key, val): Property.addValue(self, key, val) @@ -197,7 +242,7 @@ def __init__(self, name='', values=[], bases = []): Property.__init__(self, name, values, bases) - self.constraint = InverseFunctionalCardinality(name) + self.constraint = [InverseFunctionalCardinality(name)] def addValue(self, key, val): Property.addValue(self, key, val) @@ -251,6 +296,7 @@ builtin_voc = { getUriref('owl', 'Thing') : Thing, getUriref('owl', 'Class') : ClassDomain, + getUriref('rdf', 'Property') : Property, getUriref('owl', 'ObjectProperty') : ObjectProperty, getUriref('owl', 'AllDifferent') : AllDifferent , getUriref('owl', 'AnnotationProperty') : Property, #XXX AnnotationProperty, @@ -301,9 +347,15 @@ while len(list(self.graph.triples((None,)*3))) != len(self.seen.keys()): for (s, p, o) in (self.graph.triples((None,)*3)): self.consider_triple((s, p, o)) + log("%s %s" %(s,p)) + #assert len([x for x in self.variables.values() if isinstance(x, fd)])==0 log("=============================") assert len(list(self.graph.triples((None,)*3))) == len(self.seen.keys()) + def finish(self): + for key in list(self.variables.keys()): + self.variables[key].finish(self.variables, self.constraints) + def consider_triple(self,(s, p, o)): log("Trying %r" % ((s, p, o),)) if (s, p, o) in self.seen.keys(): @@ -359,61 +411,33 @@ var = str(a.replace('.','_')) var = str(a.replace('-','_')) else: - var = a + var = str(a) if not cls: return var if not var in self.variables: cls = self.variables[var] = cls(var) - if hasattr(cls, 'constraint'): + if cls.constraint: log("make_var constraint 1 %r,%r" %(cls,a)) - self.constraints.append(cls.constraint) + self.constraints.extend(cls.constraint) # XXX needed because of old style classes - elif issubclass(cls, self.variables[var].__class__): + elif not cls == self.variables[var].__class__ and issubclass(cls, self.variables[var].__class__): vals = self.variables[var].getValues() tmp = cls(var) tmp.setValues(vals) tmp.property = self.variables[var].property - tmp.TBox = self.variables[var].TBox - if hasattr(tmp, 'constraint'): + if tmp.constraint: log("make_var constraint 2 %r,%r" %(cls,a)) - self.constraints.append(tmp.constraint) + self.constraints.extend(tmp.constraint) self.variables[var] = tmp return var - def evaluate(self, terms): - # terms is a dictionary of types of restriction and list of values for this restriction - term = terms - if len(term) < 1: return - mini = maxi = equal = None - for tp,val in term: - if tp == '<': - if not maxi or val < maxi : maxi = val - elif tp == '>': - if not mini or val > mini : mini = val - else: - if equal: - raise ConsistencyFailure - equal = val - - if mini and maxi and mini > maxi: - raise ConsistencyFailure - if mini and equal and equal < mini: - raise ConsistencyFailure - if maxi and equal and equal > maxi: - raise ConsistencyFailure - - def check_TBoxes(self): - for var, cls in self.variables.items(): - for prop, terms in cls.TBox.items(): - if len(terms.get('Cardinality',[])) > 1: - self.evaluate(terms['Cardinality']) - def solve(self,verbose=0): rep = Repository(self.variables.keys(), self.variables, self.constraints) return Solver().solve(rep, verbose) def consistency(self, verbose=0): - self.check_TBoxes() + self.finish() + log("DOMAINS %r"% self.variables) self.rep = Repository(self.variables.keys(), self.variables, self.constraints) self.rep.consistency(verbose) @@ -463,12 +487,10 @@ return else: svar = self.make_var(None, s) -# if not (self.variables.has_key(svar) and -# isinstance(self.variables[svar], cls)): svar = self.make_var(cls, s) cls = self.variables[svar] - if hasattr(cls, 'constraint'): - self.constraints.append(cls.constraint) + if cls.constraint: + self.constraints.extend(cls.constraint) if not isinstance(self.variables[avar], Property): self.variables[avar].addValue(s) @@ -494,30 +516,14 @@ # class extension of var, ie if a indiviual is in # the extension of s it must be in the extension of # var + + # what I really want is to just say s.bases.append(var) + log("%r subClassOf %r "%(s, var)) - self.resolve_item(var) -# self.resolve_item(s) - avar = self.make_var(None, var) + avar = self.make_var(ClassDomain, var) svar = self.make_var(ClassDomain, s) - obj = self.variables[avar] - sub = self.variables[svar] -# assert (not isinstance(obj, Restriction)) or obj.TBox - if obj.TBox: - for key in obj.TBox.keys(): - sub.TBox.setdefault(key,{}) - prop = sub.TBox[key] - for typ in obj.TBox[key].keys(): - prop.setdefault(typ, []) - prop[typ].extend(obj.TBox[key][typ]) - -# if isinstance(self.variables[avar], Restriction): -# self.variables[avar].TBox = {} -# self.variables.pop(avar) - else: - cons = SubClassConstraint( svar, avar) - self.constraints.append(cons) - for item in obj.getValues(): - sub.addValue(item) + self.variables[svar].bases.append(avar) + self.variables[svar].bases.extend(self.variables[avar].bases) def equivalentClass(self, s, var): self.subClassOf(s, var) @@ -635,76 +641,63 @@ self.variables[avar].addValue(pair[1], pair[0]) #---Property restrictions------------------------------------------------------ - + def cardinality_helper(self, s, var, card): - self.resolve_item(s) + log("%r %sCardinality %r "%(s, card, var)) svar =self.make_var(Restriction, s) - prop = self.variables[svar].property - assert prop - cls = list(self.graph.triples((None, None, s))) - if cls: - cls = cls[0][0] - else: - cls = var - comp = {'max': '<', 'min': '>'}.get(card, '=') - self.variables[svar].TBox[prop] = {'Cardinality': [( comp, int(var))]} - self.constraints.append(CardinalityConstraint(prop, cls, var, comp+'=')) + scls = self.variables[svar] + scls.un_constraint.append(card) + scls.value = var def maxCardinality(self, s, var): """ Len of finite domain of the property shall be less than or equal to var""" - self.cardinality_helper(s, var, 'max') + def maxCard(cls , prop, val): + dom = {"%s_%s_card" %(cls, prop.name) : fd(range(val+1))} + return dom,[CardinalityConstraint( prop.name, cls, val, '<')] + self.cardinality_helper(s, int(var), maxCard) def minCardinality(self, s, var): """ Len of finite domain of the property shall be greater than or equal to var""" - self.cardinality_helper(s, var, 'min') + def minCard(cls , prop, val): + var = "%s_%s_card" %(cls, prop.name) + con = Expression([var], "%s >= %i" % (var, val)) + return {},[con, CardinalityConstraint(prop.name, cls, val , '>')] + self.cardinality_helper(s, int(var), minCard) def cardinality(self, s, var): """ Len of finite domain of the property shall be equal to var""" - self.cardinality_helper(s, var, '') - - def hasValue(self, s, var): - self.resolve_item(s) - self.resolve_item(var) + def Card(cls , prop, val): + dom = {"%s_%s_card" %(cls, prop.name) : fd([val])} + return dom,[CardinalityConstraint( prop.name, cls, val, '=')] + self.cardinality_helper(s, int(var), Card) + + def value_helper(self, s, var, constraint): svar = self.make_var(Restriction, s) avar = self.make_var(None, var) - prop = self.variables[svar].property - restr = self.variables[svar] - restr.TBox[prop] = {'hasValue' : [('hasvalue', var)]} - for cls,vals in self.variables[prop].getValuesPrKey(): - if var in vals: - self.variables[svar].addValue(cls) - + scls = self.variables[svar] + scls.un_constraint.append(constraint) + scls.value = var + + def hasValue(self, s, var): + """ The hasValue restriction defines a class having as an extension all + Individuals that have a property with the value of var. + To make an assertion we need to know for which class the restriction applies""" + + def Hasvalue(cls ,prop, val): + #The Domain of the cls should be Thing + var = "%s_%s_hasvalue" %(cls, prop.name) + dom = {var : fd(prop.getValues( ))} + cons = Expression([cls, var], "%s == %s[1] and %s == %s[0]" %(val, var, cls, var)) + return dom, [cons] + + self.value_helper(s, var, Hasvalue) + def allValuesFrom(self, s, var): - self.resolve_item(s) - self.resolve_item(var) - svar = self.make_var(Restriction, s) - avar = self.make_var(None, var) - prop = self.variables[svar].property - restr = self.variables[svar] - restr.TBox[prop] = {'allValuesFrom' : [('allValuesFrom', avar)]} - obj = self.variables[avar] - constrain_vals = set(obj.getValues()) - for cls,vals in self.variables[prop].getValuesPrKey(): - if (set(vals) & constrain_vals) == constrain_vals: - self.variables[svar].addValue(cls) - + self.value_helper(s, var, AllValueConstraint) + def someValuesFrom(self, s, var): - self.resolve_item(s) - self.resolve_item(var) - svar = self.make_var(Restriction, s) - avar = self.make_var(None, var) - prop = self.variables[svar].property - restr = self.variables[svar] - obj = self.variables.get(avar, None) - if obj: - constrain_vals = set(obj.getValues()) - else: - constrain_vals = set() - restr.TBox[prop] = {'someValuesFrom' : [('someValuesFrom', avar)]} - for cls,vals in self.variables[prop].getValuesPrKey(): - if set(vals) & constrain_vals: - self.variables[svar].addValue(cls) + self.value_helper(s, var, SomeValueConstraint) # ----------------- ---------------- @@ -732,7 +725,6 @@ def distinctMembers(self, s, var): s_var = self.make_var(AllDifferent, s) var_var = self.flatten_rdf_list(var) - #var_var = self.make_var(List, var) diff_list = self.variables[var_var].getValues() for v in diff_list: indx = diff_list.index(v) From ale at codespeak.net Tue May 30 18:22:05 2006 From: ale at codespeak.net (ale at codespeak.net) Date: Tue, 30 May 2006 18:22:05 +0200 (CEST) Subject: [pypy-svn] r27928 - pypy/dist/pypy/lib/pyontology/test Message-ID: <20060530162205.D26D210063@code0.codespeak.net> Author: ale Date: Tue May 30 18:22:05 2006 New Revision: 27928 Modified: pypy/dist/pypy/lib/pyontology/test/test_ontology.py Log: Forgot this Modified: pypy/dist/pypy/lib/pyontology/test/test_ontology.py ============================================================================== --- pypy/dist/pypy/lib/pyontology/test/test_ontology.py (original) +++ pypy/dist/pypy/lib/pyontology/test/test_ontology.py Tue May 30 18:22:05 2006 @@ -39,17 +39,16 @@ def test_subClassof(): O = Ontology() - a = O.make_var(ClassDomain,URIRef(u'A')) - b = O.make_var(ClassDomain,URIRef(u'B')) - c = O.make_var(ClassDomain,URIRef(u'C')) + a = URIRef(u'A') + b = URIRef(u'B') + c = URIRef(u'C') O.subClassOf(b, a) O.subClassOf(c, b) obj = URIRef(namespaces['owl']+'#Class') O.type(a,obj) O.consistency() - O.consistency() - assert len(O.variables) == 4 - assert 'C_' in O.variables['A_'].getValues() +# assert len(O.variables) == 4 + assert 'A_' in O.variables['C_'].bases def test_addvalue(): O = Ontology() @@ -135,7 +134,7 @@ O = Ontology() sub = URIRef('a') obj = URIRef('b') - O.variables['b_'] = fd([1,2,3,4]) + O.variables['b_'] = ClassDomain(values=[1,2,3,4]) O.range(sub, obj) sub = URIRef('a') pred = URIRef('type') @@ -315,10 +314,12 @@ O.variables['owner_'].setValues([('Bob_','Fiat_')]) O.inverseOf(own, owned) assert ('Fiat_','Bob_') in O.variables['ownedby_'].getValues() + def test_hasvalue(): + # py.test.skip("") O = Ontology() cls = URIRef('class') - obj = URIRef(namespaces['owl']+'#Class') + obj = URIRef(namespaces['owl']+'#Thing') O.type(cls, obj) restrict = BNode('anon1') obj = URIRef(namespaces['owl']+'#Restriction') @@ -328,12 +329,17 @@ O.type(p, obj) O.consider_triple((cls, p, 2)) O.onProperty(restrict,p) - O.variables['p_'].setValues([(O.make_var(None,cls),1)]) + O.consider_triple((cls, p, 1)) O.hasValue(restrict, 2) + O.type(2, URIRef(namespaces['owl']+'#Thing')) + O.type(1, URIRef(namespaces['owl']+'#Thing')) + cls2 = URIRef('class2') - obj = URIRef(namespaces['owl']+'#Class') + obj = URIRef(namespaces['owl']+'#Thing') O.type(cls2, obj) O.subClassOf(cls2,restrict) + + O.consistency() assert cls in O.variables[O.make_var(None, cls2)].getValues() # py.test.raises(ConsistencyFailure, O.consistency) @@ -374,7 +380,7 @@ assert set(O.rep._domains[restrict].getValues()) == set(own) def test_somevaluesfrom_datarange(): - + py.test.skip("reconsider if the test is correct - make it simpler") O = Ontology() datarange = BNode('anon') own = ['1','2','3'] @@ -393,9 +399,11 @@ O.onProperty(restrict,p) O.someValuesFrom(restrict, datarange) O.subClassOf(cls,restrict) + O.consistency() assert cls in O.variables[O.make_var(None, cls)].getValues() def test_allvaluesfrom_datarange(): + py.test.skip("") O = Ontology() datarange = BNode('anon') own = ['1','2','3'] @@ -521,7 +529,7 @@ O.add((cls, namespaces['rdfs']+'#subClassOf',restr2 )) O.add((restr2, namespaces['rdfs']+'#minCardinality', 3 )) O.attach_fd() - py.test.raises(ConsistencyFailure, O.check_TBoxes) + py.test.raises(ConsistencyFailure, O.consistency) def test_terminology_subclassof_cardinality(): cls = URIRef('cls') @@ -546,14 +554,13 @@ O.add((restr2, namespaces['rdfs']+'#minCardinality', 3 )) O.add((cls2, namespaces['rdfs']+'#subClassOf', cls )) O.attach_fd() - py.test.raises(ConsistencyFailure, O.check_TBoxes) - assert O.variables['cls_'].TBox == O.variables['cls2_'].TBox + py.test.raises(ConsistencyFailure, O.consistency) def test_add_file(): O = Ontology() O.add_file('premises001.rdf') trip = list(O.graph.triples((None,)*3)) - O.attach_fd() +# O.attach_fd() ll = len(O.variables) l = len(trip) O.add_file('conclusions001.rdf') @@ -565,12 +572,12 @@ O = Ontology() O.add_file('premises003.rdf') trip = list(O.graph.triples((None,)*3)) - O.attach_fd() + # O.attach_fd() ll = len(O.variables) l = len(trip) O.add_file('conclusions003.rdf') O.attach_fd() - O.check_TBoxes() + O.consistency() lll = len(O.variables) assert len(list(O.graph.triples((None,)*3))) > l @@ -631,14 +638,14 @@ assert isinstance(O.variables['a_'], Restriction) assert O.variables[O.make_var(None, a_cls)].property == "SomeProp" -def test_thing_to_property(): +def test_property_to_objectproperty(): O = Ontology() a_cls = URIRef('a') - O.type(a_cls, URIRef(namespaces['owl']+'#Thing')) - assert isinstance(O.variables['a_'], Thing) + O.type(a_cls, URIRef(namespaces['rdf']+'#Property')) + assert isinstance(O.variables['a_'], Property) O.type(a_cls, URIRef(namespaces['owl']+'#ObjectProperty')) assert isinstance(O.variables['a_'], Property) - O.type(a_cls, URIRef(namespaces['owl']+'#Thing')) + O.type(a_cls, URIRef(namespaces['rdf']+'#Property')) - assert isinstance(O.variables['a_'], Property) + assert isinstance(O.variables['a_'], ObjectProperty) From pedronis at codespeak.net Tue May 30 18:36:50 2006 From: pedronis at codespeak.net (pedronis at codespeak.net) Date: Tue, 30 May 2006 18:36:50 +0200 (CEST) Subject: [pypy-svn] r27929 - pypy/extradoc/talk/dls2006 Message-ID: <20060530163650.8E8AD10057@code0.codespeak.net> Author: pedronis Date: Tue May 30 18:36:49 2006 New Revision: 27929 Modified: pypy/extradoc/talk/dls2006/draft.bib Log: add PyPy own stuff Modified: pypy/extradoc/talk/dls2006/draft.bib ============================================================================== --- pypy/extradoc/talk/dls2006/draft.bib (original) +++ pypy/extradoc/talk/dls2006/draft.bib Tue May 30 18:36:49 2006 @@ -158,3 +158,26 @@ address = {London, UK}, } + +% PyPy doc and reports + at techreport{D, +title = {Compiling Dynamic Language Implementations}, +author = {Armin Rigo and Michael Hudson and Samuele Pedroni}, +year = {2005}, +institution = {PyPy Consortium}, +url = {http://codespeak.net/~cfbolz/eu-reports/D05.1_Publish_on_translating_a_very-high-level_description.pdf} +} + + at misc{T, +title = {PyPy - Translation}, +author = {PyPy Team}, +url = {http://codespeak.net/pypy/dist/pypy/doc/translation.html}, +howpublished = {Web page, in-progress.} +} + + at misc{A, +title = {PyPy - Architecture Overview}, +author = {PyPy Team}, +url = {http://codespeak.net/pypy/dist/pypy/doc/architecture.html}, +howpuplished = {Web page} +} From arigo at codespeak.net Tue May 30 18:37:17 2006 From: arigo at codespeak.net (arigo at codespeak.net) Date: Tue, 30 May 2006 18:37:17 +0200 (CEST) Subject: [pypy-svn] r27930 - pypy/extradoc/talk/dls2006 Message-ID: <20060530163717.DE48D1005A@code0.codespeak.net> Author: arigo Date: Tue May 30 18:37:16 2006 New Revision: 27930 Modified: pypy/extradoc/talk/dls2006/draft.txt Log: Reviewed Related work section. I guess this should be the last check-in in this draft.txt; work should now move to the LaTeX version. Modified: pypy/extradoc/talk/dls2006/draft.txt ============================================================================== --- pypy/extradoc/talk/dls2006/draft.txt (original) +++ pypy/extradoc/talk/dls2006/draft.txt Tue May 30 18:37:16 2006 @@ -1074,65 +1074,64 @@ Related work ============================================================ -Applying the expressiveness or at least syntax of very high-level and -dynamically typed languages to their implementation has been -investigated many times. +Applying the expressiveness - or at least the syntax - of very +high-level and dynamically typed languages to their implementation has +been investigated many times. -One typical approach is writing a static compiler. The viability of -and effort required for such an approach depend usually on the binding +One typical approach is writing a static compiler. The viability of, +and effort required for, such an approach depends usually on the binding and dispatch semantics of the language. Common Lisp native compilers, -usable interactively and taking functions or files as compilation -units are a well-known example of that approach. Late binding for all -names and load semantics make such an approach very hard for Python, -if speed improvements are desired. - -It is more relevant to consider and compare with projects using -dynamic and very-high level languages for interpreters and VM -implementations, and Just-In-Time compilers. - -Scheme48_ was a Scheme implementation using a restricted Scheme, with -static type inference based on Hindley-Milner, this is viable for -Scheme as base language. Portability and simplicity were its major -goals. +usable interactively and taking single functions or files as compilation +units, are a well-known example of that approach. However, the late +binding for all names and the load semantics make such an approach very +hard for Python, if speed improvements are desired. + +In this context, it is more relevant to consider and compare with +projects using dynamic and very-high-level languages for interpreters +and VM implementations, and Just-In-Time compilers. + +Scheme48 was a Scheme implementation using a restricted Scheme, +PreScheme_, with static type inference based on Hindley-Milner. This is +viable for Scheme as base language. Simplicity and portability across C +platforms were its major goals. Squeak_ is a Smalltalk implementation in Smalltalk. It uses SLang, a very restricted subset of Smalltalk with few types and strict -conventions such that mostly direct translation to C is possible. -Both the VM and the object memory and garbage collector support are +conventions, which can be mostly directly translated to C. +The VM, the object memory and the garbage collector support are explicitly written together in this style. Again simplicity and -portability were the major goals, not sophisticated manipulation and -analysis and waving in of features. +portability were the major goals, as opposed to sophisticated manipulation +and analysis or "weaving" in of features as transformation aspects. -`Jikes RVM`_ is a Java VM and Just-In-Time compiler written in Java. +Jikes RVM [DBLP:journals/ibmsj/AlpernABBCCCFGHHLLMNRSSSSSSW00] is a +Java VM and Just-In-Time compiler written in Java. Bootstrapping happens by self-applying the compiler on a host VM, and dumping a snapshot from memory of the resulting native code. - -This approach enables directly high performance, at the price of -portability as usual with pure native code emitting +This approach directly enables high performance, at the price of +portability - as usual with pure native code emitting approaches. Modularity of features, when possible, is achieved with -normal software modularity. The indirection costs are taken care by -the inlining done by the compiler, sometimes even through explicit -ways to request for it. In particular this modular approach is used -for implementing a range of choices for GC support XXX ref. This was -the inspiration for PyPy own GC framework, although much more tuning -and work went into Jikes RVM. PyPy own GC framework also exploits +normal software modularity. The indirection costs are taken care of by +the compiler performing inlining (which is sometimes even explicitly +requested). In particular this modular approach is used +for implementing a range of choices for GC support [Jikes-GC]. This was +the inspiration for PyPy's own GC framework, although much more tuning +and work went into Jikes RVM. PyPy's own GC framework also exploits inlining of helpers and barriers to recover performance. -Jikes RVM native JIT compilers can likely not easily be retargeted to -run on top and target another VM (for example a CLR runtime) instead -of hardware processors. Also Jikes RVM pays the complexity of writing +Jikes RVM's native JIT compilers [Jikes-JIT] +are not meant to be retargetted to run in other environments +that hardware processors, for example in a CLR/.NET +runtime. Also Jikes RVM pays the complexity of writing a JIT up-front, which also means that features and semantics of the -language are encoded in the JIT compiler code, meaning likely that -major changes would correspond to major surgery needed on it. +language are encoded in the JIT compiler code. Major changes of the +language are likely to correspond to major surgery of the JIT. -PyPy more indirect approach, together hopefully with our future work +PyPy's more indirect approach, together hopefully with our future work on generating a JIT compiler, tries to overcome these limitations, at -the price of some more effort required to achieve very good -performance. It is too soon to compare completely the complexity (and -performance) trade-offs of these approaches. - +the price of some more efforts required to achieve very good +performance. It is too soon for a complete comparison of the complexity, +performance and trade-offs of these approaches. -XXX Jython, IronPython, UVM. .. _`section 8`: @@ -1194,7 +1193,7 @@ .. _Dhrystone: XXX .. _Richards: XXX .. _CPython: XXX -.. _Scheme48: XXX +.. _PreScheme: XXX .. _Squeak: XXX .. _`Jikes RVM`: XXX .. _`[PE]`: XXX From mwh at codespeak.net Tue May 30 18:41:30 2006 From: mwh at codespeak.net (mwh at codespeak.net) Date: Tue, 30 May 2006 18:41:30 +0200 (CEST) Subject: [pypy-svn] r27931 - pypy/extradoc/talk/dls2006 Message-ID: <20060530164130.D26EE10057@code0.codespeak.net> Author: mwh Date: Tue May 30 18:41:27 2006 New Revision: 27931 Added: pypy/extradoc/talk/dls2006/paper.tex Log: add an initial latex version on the upside: it compiles on the downside: all the figures are in verbatim environments (this looks entertainingly awful), most things that should be \cite{foo}s are just left in as [foo]s Added: pypy/extradoc/talk/dls2006/paper.tex ============================================================================== --- (empty file) +++ pypy/extradoc/talk/dls2006/paper.tex Tue May 30 18:41:27 2006 @@ -0,0 +1,1136 @@ +\documentclass{acm_proc_article-sp} +\usepackage[colorlinks=true,linkcolor=blue,urlcolor=blue]{hyperref} + +\begin{document} + +\title{Still Missing a Cool Title} + +% title ideas: Implementing Virtual Machines in Dynamic Languages? + +\maketitle + +\begin{abstract} +The PyPy project seeks to prove both on a research and a +practical level the feasibility of writing a virtual machine (VM) +for a dynamic language in a dynamic language -- in this case, Python. +The aim is to translate (i.e. compile) the VM to arbitrary target +environments, ranging in level from C/Posix to Smalltalk/Squeak via +Java and CLI/.NET, while still being of reasonable efficiency within +these environments. + +A key tool to achieve this goal is the systematic reuse of the +(unmodified, dynamically typed) Python language as a system +programming language at various levels of our architecture and +translation process. For each level, we design a corresponding type +system and apply a generic type inference engine -- for example, the +garbage collector is written in a style that manipulates +simulated pointer and address objects, and when translated to C +these operations become C-level pointer and address instructions. +\end{abstract} + +\section{Introduction} + +Despite the constant trend in the programming world towards +portability and reusability, there are some areas in which it is still +notoriously difficult to write flexible, portable, and reasonably +efficient programs. The implementation of virtual machines is one +such area. Building implementations of general programming languages, +in particular highly dynamic ones, using a classic direct coding +approach, is typically a long-winded effort and produces a result that +is quite [quite could be removed here?] tailored to a specific +platform and where architectural decisions (e.g. about GC) are spread +across the code in a pervasive and invasive way. + +For this and other reasons, standard platforms emerge; nowadays, a +language implementer could cover most general platforms in use by +writing three versions of his virtual machine: for C/Posix, for Java, +and for CLI/.NET. This is, at least, the current situation of the +Python programming language, where independent volunteers have +developed and are now maintaining Java and .NET versions of Python, +which follow the evolution of the "official" C version (CPython). + +However, we believe that platform standardization does not have to be +a necessary component of this equation. We are basically using the +standard "meta-programming" argument: if one could write the VM in a +very high level language, then the VM itself could be automatically +\textit{translated} to any lower-level platform. Moreover by writing +the VM in such a language we would gain in flexibility in +architectural choices and expressiveness. + +PyPy achieves this goal without giving up on the efficiency of the +compiled VMs. + +The key factors enabling this result are not to be found in recent +advances in any particular research area -- we are not for example using +constraint-based type inference. Instead, we are following a novel +overall architecture: it is split into many levels of stepwise +translation from the high-level source of the VM to the final target +platform. Similar platforms can reuse many of these steps, while for +very different platforms we have the option to perform very different +translation steps. Each step reuses a common type inference component +with a different, ad-hoc type system. + +Experiments also suggest a more mundane reason why such an approach is +only practical today: a typical translation takes about half an hour +on a modern PC and consumes between 512MB and 1GB of RAM. + +We shortly describe the architecture of PyPy in section +\ref{architecture}. In section \ref{systemprog} we describe our +approach of varying the type systems at various levels of the +translation. Section \ref{typeinference} gives an overview of the +type inference engine we developed (and can be read independently from +section 3.) We present experimental results in section +\ref{experimentalresults} and future work directions in section +\ref{futurework}. In section \ref{relatedwork} we compare with +related work, and finally we conclude in section \ref{conclusion}. + +\section{Architecture} +\label{architecture} + +There are two major components in PyPy: + +\begin{enumerate} +\item the \textit{Standard Interpreter}: an implementation of the Python programming +language, mostly complete and compliant with the current version of the +language, Python 2.4. +\item the \textit{Translation Process}: a translation tool-suite whose goal is to +compile subsets of Python to various environment. +\end{enumerate} + +In particular, we have defined a subset of the Python language called +"restricted Python" or RPython. This sublanguage is not restricted +syntactically, but only in the way it manipulates objects of different +types. The restrictions are a compromise between the expressivity and +the need to statically infer enough types to generate efficient code. +The foremost purpose of the translation tool-suite is to compile such +RPython programs to a variety of different platforms. + +Our current efforts, and the present paper, focus on this tool-suite. +We will not describe the Standard Interpreter component of PyPy in the +sequel, other than mention that it is written in RPython and can thus be +translated. At close to 90,000 lines of code, it is the largest RPython +program that we have translated so far. More information can be found +in [S]. + + +\section{System programming with Python} +\label{systemprog} + +\hypertarget{the-translation-process}{} +\subsection{The translation process} +\label{translationprocess} + +The translation process starts from RPython source code and eventually +produces low-level code suitable for the target environment. It can be +described as performing a series of step-wise transformations. Each +step is based on control flow graph transformations and rewriting, and +on the ability to augment the program with further implementation code +written in Python and analysed with the suitable type system. + +The front-end part of the translation process analyses the input +RPython program in two phases, as follows\footnote{Note that the two +phases are intermingled in time, because type inference proceeds from +an entry point function and follows all calls, and thus only gradually +discovers (the reachable parts of) the input program.}: + +\begin{verbatim} +:: + + [figure 0: flow graph and annotator, e.g. part of doc/image/translation.* + then a stack of transformations + ] +\end{verbatim} + +\begin{enumerate} +\item We take as input RPython functions\footnote{The input to our + translation chain are indeed loaded runtime function objects, + not source code or ASTs. This allows us to use unrestricted + python for meta-programming purposes at load time, in a + seemingly staged programming approach, in which the whole of + the source program -- as Python program -- produces the RPython + program input to the tool-chain as the object graph loaded in + memory. This includes both the relevant functions and prebuilt + data.}, and convert them to control flow graphs -- a structure + amenable to analysis. These flow graphs contain polymorphic + operations only: in Python, almost all operations are + dynamically overloaded by type. + +\item We perform type inference on the control flow graphs. At this + stage, types inferred are part of the type system which is the + very definition of the RPython sub-language: they are roughly a + subset of Python's built-in types, with some more precision to + describe e.g. the items stored in container types. + Occasionally, a single input function can produce several + specialized versions, i.e. several similar but differently typed + graphs. This type inference process is described in more + details in section \ref{typeinference}. +\end{enumerate} + +At the end of the front-end analysis, the input RPython program is +represented as a forest of flow graphs with typed variables. Following +this analysis are a number of transformation steps. Each transformation +step modifies the graphs in-place, by altering their structure and/or +the operations they contain. Each step inputs graphs typed in one type +system and leaves them typed in a possibly different type system, as we +will describe in the sequel. Finally, a back-end turns the resulting +graphs into code suitable for the target environment, e.g. C source code +ready to be compiled. + + +\subsection{Transformations} + +When the translation target is C or C-like environments, the first of +the transformation steps takes the RPython-typed flow graphs, still +containing polymorphic operations only, and produces flow graphs with +monomorphic C-like operations and C-like types. In the simplest case, +this is the only transformation step: these graphs are directly fed to +the C back-end, which turns them into ANSI C source code. + +But RPython comes with automatic memory management, and this first +transformation step produces flow graphs that also assume automatic +memory management. Generating C code directly from there produces a +fully leaking program, unless we link it with an external garbage +collector (GC) like the Boehm conservative GC [Boehm], which is a +viable option. + +We have two alternatives, each implemented as a transformation step. +The first one inserts naive reference counting throughout the whole +program's graphs, which without further optimizations gives exceedingly +bad performance (it should be noted that the CPython interpreter is also +based on reference counting, and experience suggests that it was not a +bad choice in this particular case). + +The other, and better, alternative is an exact GC, coupled with a +transformation, the \textit{GC transformer}. It inputs C-level-typed graphs +and replaces all \texttt{malloc} operations with calls to a garbage +collector's innards. It can inspect all the graphs to discover the +\texttt{struct} types in use by the program, and assign a unique type id to +each of them. These type ids are collected in internal tables that +describe the layout of the structures, e.g. their sizes and the location +of the pointer fields. + +We have implemented other transformations as well, e.g. performing +various optimizations, or turning the whole code into a +continuation-passing style (CPS) [I'm not sure our transformation +can be classified as classical CPS, although there are known similar techniques but the terminology is quite confused] that allows us to use coroutines +without giving up the ability to generate fully ANSI C code. (This will +be the subject of another paper.) [mention exception transformer too] + +Finally, currently under development is a variant of the very first +transformation step, for use when targeting higher-level, +object-oriented (OO) environments. It is currently being designed +together with back-ends for Smalltalk/Squeak\footnote{Our simple OO +type system is designed for \textit{statically-typed} OO environments, +including Java; the presence of Smalltalk as a back-end might be +misleading in that respect.} and CLI/.NET. This first transformation +step, for C-like environments, is called the \textit{LLTyper}: it produces +C-level flow graphs, where the object-oriented features of RPython +(classes and instances) become manipulations of C structs with +explicit virtual table pointers. By contrast, for OO environments the +transformation step is called the \textit{OOTyper}: it targets a simple +object-oriented type system, and preserves the classes and instances +of the original RPython program. The LLTyper and OOTyper still have +much code in common, to convert the more Python-specific features like +its complex calling conventions. + +More information about these transformations can be found in [T]. + + +\subsection{System code} + +A common pattern in all the transformation steps is to somehow lower the +level at which the graphs are currently expressed. Because of this, +there are operations that were atomic in the input (higher-level) graphs +but that need to be decomposed into several operations in the target +(lower-level) graphs. In some cases, the equivalent functionality +requires more than a couple of operations: a single operation must be +replaced by a call to whole new code -- functions and classes that serve +as helpers. An example of this is the \texttt{malloc} operation for the GC +transformer. Another example is the \texttt{list.append()} method, which is +atomic for Python or RPython programs, but needs to be replaced in +C-level code by a helper that possibly reallocates the array of items. + +This means that in addition to transforming the existing graphs, each +transformation step also needs to insert new functions into the forest. +A key feature of our approach is that we can write such "system-level" +code -- relevant only to a particular transformation -- in plain Python +as well: + +\begin{verbatim} +.. topic:: Figure 1 - a helper to implement \texttt{list.append()} + + :: + + def ll_append(lst, newitem): + # Append an item to the end of the vector. + index = lst.length # get the 'length' field + ll_resize(lst, index+1) # call a helper not shown here + itemsarray = lst.items # get the 'items' field + itemsarray[index] = item # this behaves like a C array +\end{verbatim} + +The idea is to feed these new Python functions into the front-end, using +this time the transformation's target (lower-level) type system during +the type inference. In other words, we can write plain Python code that +manipulates objects that conform to the lower-level type system, and +have these functions automatically transformed into appropriately typed +graphs. + +For example, \texttt{ll\textunderscore{}append()} in figure 1 is a Python function +that manipulates objects that behave like C structures and arrays. +This function is inserted by the LLTyper, as a helper to implement the +\texttt{list.append()} calls found in its RPython-level input graphs. +By going through the front-end reconfigured to use C-level types, the +above function becomes a graph with such C-level types\footnote{The +low-level type system specifies that the function should be +specialized by the C-level type of its input arguments, so it actually +turns into one graph per list type -- list of integers, list of +pointers, etc. This behavior gives the programmer a feeling +comparable to C++ templates, without the declarations.}, which is then +indistinguishable from the other graphs of the forest produced by the +LLTyper. + +In the example of the \texttt{malloc} operation, replaced by a call to GC +code, this GC code can invoke a complete collection of dead objects, and +can thus be arbitrarily complicated. Still, our GC code is entirely +written in plain Python, and it manipulates "objects" that are still at +a lower level: pointer and address objects. Even with the restriction +of having to use pointer-like and address-like objects, Python remains +more expressive than, say, C to write a GC. [see also Jikes] + +In the sequel, we will call \textit{system code} functions written in +Python that are meant to be analysed by the front-end. For the +purpose of this article we will restrict this definition to helpers +introduced by transformations, as opposed to the original RPython +program, although the difference is not fundamental to the translation +process (and although our input RPython program, as seen in section +\ref{architecture}, is often itself a Python virtual machine!). + +Note that such system code cannot typically be expressed as normal +RPython functions, because it corresponds to primitive operations at +that level. As an aside, let us remark that the number of primitive +operations at RPython level is, comparatively speaking, quite large: +all list and dictionary operations, instance and class attribute +accesses, many string processing methods, a good subset of all Python +built-in functions... Compared to other approaches [e.g. Squeak], we +do not try to minimize the number of primitives -- at least not at the +source level. It is fine to have many primitives at any high enough +level, because they can all be implemented at the next lower level in +a way that makes sense to that level. The key reason why this is not +burdensome is that the lower level implementations are also written in +Python -- with the only difference that they use (and have to be +typeable in) the lower-level type system\footnote{This is not strictly +true: the type systems are even allowed to co-exist in the same +function. The operations involving higher-level type systems are +turned into lower-level operations by the previous transformations in +the chain, which leave the already-low-level operations untouched.}. + + +\subsection{Type systems} + +The four levels that we considered so far are summarized in figure 2. + +\begin{verbatim} +:: + + [figure 2: RPython + / \ + / \ + LLTypeSystem OOTypeSystem + / + / + Raw addresses + ] +\end{verbatim} + +The RPython level is a subset of Python, so the types mostly follow +Python types, and the instances of these types are instances in the +normal Python sense; e.g. whereas Python has only got a single type +\texttt{list}, RPython has a parametric type \texttt{list(T)} for every RPython +type \texttt{T}, but instances of \texttt{list(T)} are just those Python lists +whose items are all instances of \texttt{T}. + +The other type systems, however, do not correspond to built-in Python +types. For each of them, we implemented: + +\begin{enumerate} +\item the types, which we use to tag the variables of the graphs at + the given level. (Types are actually annotated, self-recursive + formal terms, and would have been implemented simply as such if + Python supported them directly.) + +\item the Python objects that emulate instances of these types. (More + about them below.) +\end{enumerate} + +We have defined well-typed operations between variables of these types, +plugging on the standard Python operators. These operations are the +ones that the emulating instances implement. As seen above, the types +can also be used by type inference when analysing system code like the +helpers of figure 1. + +Now, clearly, the purpose of types like a "C-like struct" or a "C-like +array" is to be translated to a real \texttt{struct} or array declaration by +the C back-end. What, then, is the purpose of emulating such things in +Python? The answer is three-fold. Firstly, if we have objects that +live within the Python interpreter, but faithfully emulate the behavior +of their C equivalent while performing additional safety checks, they +are an invaluable help for testing and debugging. For example, we can +check the correctness of our hash table implementation, written in +Python in term of struct- and array-like objects, just by running it. +The same holds for the GC. + +Secondly, and anecdotically, as the type inference process (section +\ref{typeinference}) is based on abstract interpretation, we can use +the following trick: the resulting type of most low-level operations +is deduced simply by example. Sample C-level objects are +instantiated, used as arguments to a given operation, and produce a +sample result, whose C-level type must be the type of the result +variable in the graph. + +The third reason is fundamental: we use these emulating objects to +\textit{represent} pre-built objects at that level. For example, the GC +transformer instantiates the objects emulating C arrays for the internal +type id tables, and it fills them with the correct values. These array +objects are then either used directly when testing the GC, or translated +by the C back-end into static pre-initialized arrays. + + + +\section{Type inference} +\label{typeinference} + + +The various analyses used -- from type inference to lifetime analysis - +are generally formulated as [abstract interpretation]. While this +approach is known to be less efficient than more tailored algorithms +like constraint-based type inference, we gain in freedom, +controllability and simplicity. This proved essential in our overall +approach: as described in section \ref{systemprog}, we need to perform +type inference with many different type systems, the details of which +have evolved along the road. + +We mitigate the potential efficiency problem by wise choices and +compromises for the domain used; the foremost example of this is that +our RPython type inference performs almost no automatic specialization +of functions XXX class annotation vs concrete runtime class setsXXX. +We achieved enough precision for our purpose, though. + +In the sequel, we give a more precise description of this process and +justify our claim that good performance and enough precision can be +achieved -- at least in some contexts -- without giving up the naive but +flexible approach. + + +\subsection{Building control flow graphs} +\label{flowobjspace} +\hypertarget{flowobjspace}{} + +As described in the overview of \href{\#the-translation-process}{the +translation process}, the front-end of the translation tool-chain +works in two phases: it first builds control flow graphs from Python +functions, and then performs whole-program type inference on these +graphs. + +Remember that building the control flow graphs is not done, as one might +first expect, by following a function at the syntactic level. Instead, +the whole program is imported in a normal Python interpreter; the full +Python language is used at this point as a kind of preprocessor with +meta-programming capabilities. Once the program is imported, the object +data in memory consists of Python function objects in bytecode format, +and any other kind of objects created at import-time, like class +objects, prebuilt instances of those, prebuilt tables, and so on. Note +that these objects have typically no text representation any more; for +example, cyclic data structures may have been built at this point. The +translation tool-chain first turns these function objects into in-memory +control flow graphs which contain direct references to the prebuilt data +objects, and then handles and transforms these graphs. + +We found in-process debugging sufficient and did not implement dumping +of any intermediate step to disk. Figure 3 shows the control flow graph +obtained for a simple function -- this is a screenshot from our graph +viewer, used for debugging; basic block placement is performed by +[Graphviz]. + +\begin{verbatim} +:: + + [figure 3: insert a nice pygame screenshot] +\end{verbatim} + +The actual transformation from function objects -- i.e. bytecode -- to +flow graph is performed by the Flow Object Space, a short but generic +plug-in component for the Python interpreter of PyPy. The architecture +of our Python interpreter is shown in figure 4. + +\begin{verbatim} +.. topic:: Figure 4 - the interpreter and object spaces + + +------------------------------------------------------+ + | forest of bytecode objects from the application | + +------------------------------------------------------+ + | Python bytecode interpreter | + +--------------------------------+---------------------+ + | Standard Object Space | Flow Object Space | + +--------------------------------+---------------------+ +\end{verbatim} + +Note that the left column, i.e. the bytecode interpreter and the +Standard Object Space, form the full Python interpreter of PyPy. It is +an RPython program, and the whole purpose of the translation process is +to accept this as \textit{input}, and translate it to an efficient form. Its +architecture is not relevant to the way it is translated. XXX? + +However, the bytecode interpreter plays a double role, at two different +levels. The so-called Object Spaces are \textit{domains} in the abstract +interpretation terminology. By design, we cleanly separated these +domains from the bytecode interpreter core; the latter is only +responsible for decoding the bytecodes of an application and emulating +the corresponding stack machine. It treats all actual application-level +objects as black boxes, and dispatches all operations on them to the +Object Space. The Standard Object Space is a concrete domain, in which +objects are the concrete Python objects of the various built-in types: +lists, dictionaries, and so on. By opposition, the Flow Object Space is +really an abstract domain. It handles objects that are placeholders. +Its lattice order is shown in figure 5. + +\begin{verbatim} +:: + + [figure 5: Variable + + / | \ \ + / | \ \ + / | \ \ + Constant(1) ... Constant(n) ... Constant([1,2,3]) ... Constant() ... + ] +\end{verbatim} + +This order is extremely simple, because most actual analysis is delayed +to the next phase, the type inference engine. The objects are either +\textit{Variables}, which are pure placeholders for entierely unknown values, +or \textit{Constants} with a concrete Python object as value. The order places +Variable as the top, and keeps all \textit{Constants} unordered. Thus if two +different constants merge during abstract interpretation, we immediately +widen them to Variable. + +In conjunction with the Flow Object Space, the bytecode interpreter of +PyPy thus performs abstract interpretation of Python bytecodes from +the application\footnote{Note that this process uses the +\textit{unmodified} bytecode interpreter. This means that it is +independent of most language details. Changes in syntax or in +bytecode format or opcode semantics only need to be implemented once, +in the bytecode interpreter. In effect, the Flow Object Space enables +an interpreter for \textit{any} language to work as a front-end for +the rest of the tool-chain.}. In this case, the bytecodes in +question come from the RPython application that we would like to +translate. + +The Flow Object Space records all operations that the bytecode +interpreter "would like" to do between the placeholder objects. It +records them into basic block objects that will eventually be part of +the control flow graph of the whole function. The recorded operations +take Variables and Constants as argument, and produce new Variables as +results. The Constants serve two purposes: they are a way to +introduce constant values into the flow graphs -- these values may be +arbitrarily complex objects, not just primitives -- and they allow +basic constant propagation\footnote{This is useful at this level for +some constructs of the bytecode interpreter, which can temporarily +wrap internal values and push them onto the regular value stack among +the other application-level objects. We need to be able to unwrap +them again later. XXX compile-time computation in the helpers.} + +In the flow graph, branching occurs when the bytecode interpreter tries +to inspect the truth value of placeholder objects, as it would in +response to conditional jump opcodes or other more complicated opcodes: +at this point, the Flow Object Space starts two new basic blocks and - +with a technique akin to continuations -- tricks the interpreter into +following both branches, one after the other. Additionally, the +bytecode interpreter sends simple positional signals that allow the Flow +Object Space to detect when control paths merge, or when loops close. +In this way, abstract interpretation quickly terminates and the recorded +operations form a graph, which is the control flow graph of the original +bytecode. + +Note that we produce flow graphs in Static Single Information (SSI) +form, an extension of Static Single Assignment ([SSA]): each variable is +only used in exactly one basic block. All variables that are not dead +at the end of a basic block are explicitly carried over to the next +block and renamed. + +While the Flow Object Space is quite a short piece of code -- its core +functionality holds in 300 lines -- the detail of the interactions +sketched above is not entierely straightforward; we refer the reader to +[D] for more information. + + +\subsection{The Annotator} + +The type inference engine, which we call the \textit{annotator}, is the central +component of the front-end part of the translation process. Given a +program considered as a family of control flow graphs, the annotator +assigns to each variable of each graph a so-called \textit{annotation}, which +describes the possible run-time objects that this variable can contain. +Following usual terminology, we will call such annotations \textit{types} -- not +to be confused with the Python notion of the concrete type of an object. +An annotation is a set of possible values, and such a set is not always +the set of all objects of a specific Python type. + +Here is a simplified, static model of how the annotator works. It can +be considered as taking as input a finite family of functions calling +each other, and working on the control flow graphs of each of these +functions as built by the \href{flowobjspace}{Flow Object Space}. +Additionally, for a particular "entry point" function, the annotator +is provided with user-specified types for the function's arguments. + +The goal of the annotator is to find the most precise type that can be +given to each variable of all control flow graphs while respecting the +constraints imposed by the operations in which these variables are +involved. + +More precisely, it is usually possible to deduce information about the +result variable of an operation given information about its arguments. +For example, we can say that the addition of two integers must be an +integer. Most programming languages have this property. However, +Python -- like many languages not specifically designed with type +inference in mind -- does not possess a type system that allows much +useful information to be derived about variables based on how they are +\textit{used}; only on how they were \textit{produced}. For example, a number of very +different built-in types can be involved in an addition; the meaning of +the addition and the type of the result depends on the type of the input +arguments. Merely knowing that a variable will be used in an addition +does not give much information per se. For this reason, our annotator +works by flowing types forward, operation after operation, i.e. by +performing abstract interpretation of the flow graphs. In a sense, it +is a more naive approach than the one taken by type systems specifically +designed to enable more advanced inference algorithms. For example, +Hindley-Milner type inference works in an inside-out direction, by +starting from individual operations and propagating type constraints +outwards [H-M]. + +Naturally, simply propagating types forward requires the use of a fixed +point algorithm in the presence of loops in the flow graphs or in the +inter-procedural call graph. Indeed, we flow types forward from the +beginning of the entry point function into each basic block, operation +after operation, and follow all calls recursively. During this process, +each variable along the way gets a type. In various cases, e.g. when we +close a loop, the previously assigned types can be found to be too +restrictive. In this case, we generalise them to allow for a larger set +of possible run-time values, and schedule the block where they appear +for reflowing. The more general type can generalise the types of the +results of the variables in the block, which in turn can generalise the +types that flow into the following blocks, and so on. This process +continues until a fixed point is reached. + +We can consider that all variables are initially assigned the "bottom" +type corresponding to the empty set of possible run-time values. Types +can only ever be generalised, and the model is simple enough to show +that there is no infinite chain of generalisation, so that this process +necessarily terminates. + + +\subsection{RPython types} + +As seen in section \ref{systemprog}, we use the annotator with more than one type +systems. The more interesting and complex one is the RPython type +system, which describes how the input RPython program can be annotated. +The other type systems contain lower-level, C-like types that are mostly +unordered, thus forming more trivial lattices than the one formed by +RPython types. + +The set $A$ of RPython types is defined as the following formal terms: + +\begin{itemize} +\item $Bot$, $Top$ -- the minimum and maximum elements (corresponding + to "impossible value" and "most general value"); + +\item $Int$, $NonNegInt$, $Bool$ -- integers, known-non-negative + integers, booleans; + +\item $Str$, $Char$ -- strings, characters (which are strings of + length 1); + +\item $Inst(class)$ -- instance of $class$ or a subclass thereof + (there is one such term per $class$); + +\item $List(v)$ -- list; $v$ is a variable summarising the items of + the list (there is one such term per variable); + +\item $Pbc(set)$ -- where the $set$ is a subset of the (finite) set of + all prebuilt constant objects. This set includes all the + callables of the input program: functions, classes, and methods. + +\item $None$ -- stands for the singleton \texttt{None} object of + Python. + +\item $NullableStr$, $NullableInst(class)$ -- a string or + \texttt{None}; resp. an instance or \texttt{None}. +\end{itemize} + +Figures 6 and 7 shows how these types are ordered to form a lattice. We +mostly use its structure of [join-semilattice] only. + +\begin{verbatim} +.. graphviz:: image/lattice1.dot + +:Figure 6: the lattice of annotations. +\end{verbatim} + +\begin{verbatim} +.. graphviz:: image/lattice2.dot + +:Figure 7: The part about instances and nullable instances, assuming a + simple class hierarchy with only two direct subclasses of + \texttt{object}. +\end{verbatim} + + +All list terms for all variables are unordered. The Pbcs form a +classical finite set-of-subsets lattice. In addition, we have left +out a number of other annotations that are irrelevant for the basic +description of the annotator and straightforward to handle: +$Dictionary$, $Tuple$, $Float$, $UnicodePoint$, $Iterator$, etc. The +complete list is described in [T]. + +The type system moreover comes with a family of rules, which for every +operation and every sensible combination of input types describes the +type of its result variable. Let $V$ be the set of Variables that +appear in the user program's flow graphs. Let $b$ be a map from $V$ +to $A$; it is a "binding" that gives to each variable a type. The +purpose of the annotator is to compute such a binding stepwise. + +Let $x$, $y$ and $z$ be Variables. We introduce the rule: + +% XXX format this! +$$ +\begin{array}{c} + z = \mathrm{add}(x, y), \; b(x) = + Int, \; Bool \leq b(y) \leq Int \\ \hline + b' = b \hbox{\ with\ } (z + \rightarrow Int) +\end{array} +$$ + +which specify that if we see the addition operation applied to +Variables whose current binding is $Int$, a new binding $b'$ can be +produced: it is $b$ except on $z$, where we have $b'(z) = Int$. + +The type inference engine can be seen as applying this kind of rules +repeatedly. It does not apply them in random order, but follows a +forward-propagation order typical of abstract interpretation. + +It is outside the scope of the present paper to describe the type +inference engine and the rules more formally. The difficult points +involve mutable containers -- e.g. initially empty list that are filled +somewhere else -- and the discovery of instance attributes -- in Python, +classes do not declare upfront a fixed set of attributes for their +instances, let alone their types. Both these examples require +sophisticated reflowing techniques that invalidate existing types in +already-annotated basic blocks, to account for the influence of more +general types coming indirectly from a possibly distant part of the +program. The reader is referred to [D] for more information. + + +\subsection{Termination and complexity} + +The lattice model clearly contains no infinite chain. Moreover, it is +designed to convince oneself that the number of reflowings required in +practice is small. For example, we are not trying to do range analysis +beyond detecting non-negatives -- the reason is that range analysis is +not an essential part of writing \textit{reasonably} efficient code. Consider +that a translated RPython program runs hundreds of times faster than +when the same program is executed by the standard Python interpreter: in +this context, range analysis appears less critical. It is a possible +optimization that we can introduce in a later, optional analysis and +transformation step. + +The worst case behaviors that can appear in the model described above +involve the lattice of Pbcs, involving variables that could contain +e.g. one function object among many. An example of such behavior is +code manipulating a table of function objects: when an item is read +out of the table, its type is a large Pbc set: $Pbc(\{f1, f2, f3, +\ldots\})$. But in this example, the whole set is available at once, +and not built incrementally by successive discoveries. This seems to +be often the case in practice: it is not very common for programs to +manipulate objects that belong to a large but finite family -- and when +they do, the whole family tends to be available early on, requiring +few reflowing. + +This means that \textit{in practice} the complete process requires a time that +is far lower than the worst case. We have experimentally confirmed +this: annotating the whole PyPy interpreter (90,000 lines) takes on the +order of 5 to 10 minutes, and basic blocks are typically only reflown a +handful of times, providing a close-to-linear practical complexity. + +We give formal termination and correctness proofs in [D], as well as +worst-case bounds and some experimental evidence of their practical +irrelevance. + + +\subsection{Precision} + +Of course, this would be pointless if the annotation did not give +precise enough information for our needs. We must describe a detail of +the abstract interpretation engine that is critical for precision: the +propagation of conditional types. Consider the following source code +fragment:: + + if isinstance(x, MyClass): + f(x) + else: + g(x) + +Although the type of \texttt{x} may be some parent class of +\texttt{MyClass}, it can be deduced to be of the more precise type +$Inst(MyClass)$ within the positive branch of the \texttt{if}. +(Remember that our graphs are in SSI form, which means that the +\texttt{x} inside each basic block is a different Variable with a +possibly different type as annotation.) XXX flow sensivity and SSA + +This is implemented by introducing an extended family of types for +boolean values: + +$$ +Bool(v_1: (t_1, f_1), v_2: (t_2, f_2), ...) +$$ + +where the $v_n$ are variables and $t_n$ and $f_n$ are types. The +result of a check, like \texttt{isintance()} above, is typically +annotated with such an extended $Bool$. The meaning of the type is as +follows: if the run-time value of the boolean is True, then we know +that each variable $v_n$ has a type at most as general as $t_n$; and +if the boolean is False, then each variable $v_n$ has a type at most +as general as $f_n$. This information is propagated from the check +operation to the exit of the block via such an extended $Bool$ type, +and the conditional exit logic in the type inference engine uses it to +trim the types it propagates into the next blocks (this is where the +\textit{meet} of the lattice is used). + +With the help of the above technique, we achieve a reasonable precision +in small examples. For larger examples, a different, non-local +technique is required: the specialization of functions. XXX use 'polymorphism' + +As described in the introduction, the most important downside of our +approach is that automatic specialization is a potential +performance-killer. We \textit{do} support specialization, however: we can +generate several independently-annotated copies of the flow graphs of +certain functions. When annotating RPython programs, such +specialization does not happen automatically: we rely on hints provided +by the programmer in the source code, in the form of flags attached to +function objects. As we had this trade-off in mind when we wrote the +Python interpreter of PyPy, we only had to add a dozen or so hints in +the end. + +This does not mean that automatic specialization policies are difficult +to implement. Indeed, the simpler lower-level type systems rely quite +heavily on them: this is because the system code helpers are often +generic and can receive arguments of various C-level types. In this +case, because the types at this level are limited and mostly unordered, +specializing all functions on their input argument's types works well. + +At the level of RPython, on the other hand, the range of specializations +that make sense is much wider. We have used anything between +specialization by the type of an argument, to specialization by an +expected-to-be-constant argument value, to memoized functions that the +type inference engine will actually call during annotation and replace +by look-up tables, to complete overriding of the annotator's behavior in +extreme cases. In this sense, the need for manual specialization turned +into an advantage, in term of simplicity and flexibility of implementing +and using new specialization schemes. + +This conclusion can be generalized. We experimented with a simple +approach to type inference that works well in practice, and that can +very flexibly accomodate changes in the type system and even completely +different type systems. We think that the reasons for this success are +to be found on the one hand in the (reasonable) restrictions we put on +ourselves when designing the RPython language and writing the Python +interpreter of PyPy in RPython, and on the other hand in an ad-hoc type +system that is designed to produce enough precision (but not more) for +the purpose of the subsequent transformations to C-level code. + +We should mention that restricting oneself to write RPython code instead +of Python is still a burden, and that we are not proposing in any way +that the Python language itself should evolve in this direction, nor +even that RPython usage should become widespread. It is a tool designed +with a specific goal in mind, which is the ability to produce reasonably +efficient, stand-alone code in a large variety of environment. + + + +\section{Experimental results} +\label{experimentalresults} + + +\subsection{Performance} + +Our tool-chain is capable of translating the Python interpreter of +PyPy, written in RPython, producing right now either ANSI C code as +described before, or LLVM\footnote{the LLVM project is the realisation +of a portable assembler infrastructure, offering both a virtual +machine with JIT capabilities and static compilation. Currently we are +using the latter with its good high-level optimisations for PyPy.} +assembler which is then natively compiled with LLVM tools. + +The tool-chain has been tested with and can sucessfully apply +transformations enabling various combinations of features. The +translated interpreters are benchmarked using pystone (a [Dhrystone] +derivative traditionally used by the Python community, although it is a +rather poor benchmark) and the classical [Richards] benchmark and +compared against [CPython] 2.4.3 results: + +\begin{verbatim} ++------------------------------------+-------------------+-------------------+ +| Interpreter | Richards, | Pystone, | +| | Time/iteration | Iterations/second | ++====================================+===================+===================+ +| CPython 2.4.3 | 789ms (1.0x) | 40322 (1.0x) | ++------------------------------------+-------------------+-------------------+ +| pypy-c | 4269ms (5.4x) | 7587 (5.3x) | ++------------------------------------+-------------------+-------------------+ +| pypy-c-thread | 4552ms (5.8x) | 7122 (5.7x) | ++------------------------------------+-------------------+-------------------+ +| pypy-c-stackless | XXX (6.0x) | XXX (6.2x) | ++------------------------------------+-------------------+-------------------+ +| pypy-c-gcframework | 6327ms (8.0x) | 4960 (8.1x) | ++------------------------------------+-------------------+-------------------+ +| pypy-c-stackless-gcframework | XXX ( ) | XXX ( ) | ++------------------------------------+-------------------+-------------------+ +| pypy-llvm-c | 3797ms (4.8x) | 7763 (5.2x) | ++------------------------------------+-------------------+-------------------+ +| pypy-llvm-c-prof | 2772ms (3.5x) | 10245 (3.9x) | ++------------------------------------+-------------------+-------------------+ +\end{verbatim} + +The numbers in parenthesis are slow-down factors compared to CPython. +These measures reflect PyPy revision 27815, compiled with GCC 3.4.4. +LLVM is version 1.8cvs (May 11, 2006). The machine runs GNU/Linux SMP +on an Intel(R) Pentium(R) 4 CPU at 3.20GHz with 2GB of RAM and 1MB of +cache. The rows correspond to variants of the translation process, as +follows: + +pypy-c + The simplest variant: translated to C code with no explicit memory + management, and linked with the Boehm conservative GC [Boehm]. + +pypy-c-thread + The same, with OS thread support enabled. (For measurement purposes, + thread support is kept separate because it has an impact on the GC + performance.) + +pypy-c-stackless + The same as pypy-c, plus the "stackless transformation" step which + modifies the flow graph of all functions in a way that allows them + to save and restore their local state, as a way to enable coroutines. + +pypy-c-gcframework + In this variant, the "gc transformation" step inserts explicit + memory management and a simple mark-and-sweep GC implementation. + The resulting program is not linked with Boehm. Note that it is not + possible to find all roots from the C stack in portable C; instead, + in this variant each function explicitly pushes and pops all roots + to an alternate stack around each subcall. + +pypy-c-stackless-gcframework + This variant combines the "gc transformation" step with the + "stackless transformation" step. The overhead introduced by the + stackless feature is balanced with the removal of the overhead of + pushing and popping roots explicitly on an alternate stack: indeed, + in this variant it is possible to ask the functions in the current C + call chain to save their local state and return. This has the + side-effect of moving all roots to the heap, where the GC can find + them. + +pypy-llvm-c + The same as pypy-c, but using the LLVM back-end instead of the C + back-end. The LLVM assembler-compiler gives the best results when - + as we do here -- it optimizes its input and generates again C code, + which is fed to GCC. + +pypy-llvm-c-prof + The same as pypy-llvm-c, but using GCC's profile-driven + optimizations. + +The speed difference with CPython 2.4.3 can be explained at two levels. +One is that CPython is hand-crafted C code that has been continuously +optimized for a decade now, whereas the Python interpreter of PyPy first +seeks flexibility and high abstraction levels. The other, probably +dominant, factor is that various indices show that our approach places a +very high load on the GC and on the memory caches of the machine. The +Boehm GC is known to be less efficient than more customized approach; +kernel-level profiling shows that pypy-c typically spends 30% of its +time in the Boehm library. Our current, naively simple mark-and-sweep +GC is even quite worse. The interaction with processor caches is also +hard to predict and account for; in general, we tend to produce +relatively large amounts of code and prebuilt data. + + +\subsection{Translation times} + +A complete translation of the pypy-c variant takes about 39 minutes, +divided as follows: + +\begin{verbatim} ++-------------------------------------------+------------------------------+ +| Step | Time (minutes:seconds) | ++===========================================+==============================+ +| Front-end | 9:01 | +| (flow graphs and type inference) | | ++-------------------------------------------+------------------------------+ +| LLTyper | 10:38 | +| (from RPython-level to C-level graphs | | +| and data) | | ++-------------------------------------------+------------------------------+ +| Various low-level optimizations | 6:51 | +| (convert some heap allocations to local | | +| variables, inlining, ...) | | ++-------------------------------------------+------------------------------+ +| Database building | 8:39 | +| (this initial back-end step follows all | | +| graphs and prebuilt data structures | | +| recursively, assigns names, and orders | | +| them suitably for code generation) | | ++-------------------------------------------+------------------------------+ +| Generating C source | 2:25 | ++-------------------------------------------+------------------------------+ +| Compiling (\texttt{gcc -O2}) | 3:23 | ++-------------------------------------------+------------------------------+ +\end{verbatim} + +An interesting feature of this table is that type inference is not the +bottleneck. Indeed, further transformation steps typically take longer +than type inference alone. This is the case for the LLTyper step, +although it has a linear complexity on the size of its input (most +transformations do). + +Other transformations like the "gc" and the "stackless" ones actually +take more time, particuarly when used in combination with each other (we +speculate it is because of the increase in size caused by the previous +transformations). A translation of pypy-c-stackless, without counting +GCC time, takes 60 minutes; the same for pypy-c-stackless-gcframework +takes XXX minutes. + + + +\section{Future work} +\label{futurework} + + +As described in section \ref{experimentalresults}, the performance of +the compiled Python interpreters is still not up to competing with the +well-established CPython. We are always working to improve matters, +considering new optimizations and better GCs. Also, the OOTyper and +back-ends for Smalltalk/Squeak and CLI/.NET are currently in progress. + + +\subsection{JIT Specializer} + +So far, the PyPy tool-chain can only translate the Python interpreter of +PyPy into a program which is again an interpreter -- the same interpreter +translated to C, essentially, although we have already shown that some +aspects can be "weaved" in at translation time, like support for +coroutines. + +To achieve high performance for dynamic languages such as Python, the +proven approach is to use dynamic compilation techniques, i.e. to write +JITs. With direct techniques, this is however a major endeavour, and +increases the efforts to further evolve the language. + +In the context of the PyPy project, we are now exploring -- as we planned +from the start -- the possibility to produce a JIT as a graph +transformation aspect from the Python interpreter. This idea is based +on the theoretical possibiliy to turn interpreters into compilers by +partial evaluation [PE]. In our approach, this is done by analysing +the forest of flow graphs built from the Python interpreter, which is a +well-suited input for this kind of techniques. We can currently perform +binding-time analysis [BTA] on these graphs, again with abstract +interpretation techniques reusing the type inference engine. The next +step is to transform the graphs -- following the binding-time annotations +- into a compiler; more precisely, in partial evalution terminology, a +generating extension. We can currently do this on trivial examples. + +The resulting generating extension will be essentially similar to +[Psyco], which is the only (and hand-written) JIT available for Python so +far, based on run-time specialization. + + + +\section{Related work} +\label{relatedwork} + +Applying the expressiveness or at least syntax of very high-level and +dynamically typed languages to their implementation has been +investigated many times. + +One typical approach is writing a static compiler. The viability of +and effort required for such an approach depend usually on the binding +and dispatch semantics of the language. Common Lisp native compilers, +usable interactively and taking functions or files as compilation +units are a well-known example of that approach. Late binding for all +names and load semantics make such an approach very hard for Python, +if speed improvements are desired. + +It is more relevant to consider and compare with projects using +dynamic and very-high level languages for interpreters and VM +implementations, and Just-In-Time compilers. + +[Scheme48] was a Scheme implementation using a restricted Scheme, with +static type inference based on Hindley-Milner, this is viable for +Scheme as base language. Portability and simplicity were its major +goals. + +[Squeak] is a Smalltalk implementation in Smalltalk. It uses SLang, a +very restricted subset of Smalltalk with few types and strict +conventions such that mostly direct translation to C is possible. +Both the VM and the object memory and garbage collector support are +explicitly written together in this style. Again simplicity and +portability were the major goals, not sophisticated manipulation and +analysis and waving in of features. + +[Jikes RVM] is a Java VM and Just-In-Time compiler written in Java. +Bootstrapping happens by self-applying the compiler on a host VM, and +dumping a snapshot from memory of the resulting native code. + +This approach enables directly high performance, at the price of +portability as usual with pure native code emitting +approaches. Modularity of features, when possible, is achieved with +normal software modularity. The indirection costs are taken care by +the inlining done by the compiler, sometimes even through explicit +ways to request for it. In particular this modular approach is used +for implementing a range of choices for GC support XXX ref. This was +the inspiration for PyPy own GC framework, although much more tuning +and work went into Jikes RVM. PyPy own GC framework also exploits +inlining of helpers and barriers to recover performance. + +Jikes RVM native JIT compilers can likely not easily be retargeted to +run on top and target another VM (for example a CLR runtime) instead +of hardware processors. Also Jikes RVM pays the complexity of writing +a JIT up-front, which also means that features and semantics of the +language are encoded in the JIT compiler code, meaning likely that +major changes would correspond to major surgery needed on it. + +PyPy more indirect approach, together hopefully with our future work +on generating a JIT compiler, tries to overcome these limitations, at +the price of some more effort required to achieve very good +performance. It is too soon to compare completely the complexity (and +performance) trade-offs of these approaches. + + +XXX Jython, IronPython, UVM. + +\section{Conclusion} +\label{conclusion} + + +XXX + +nice interpreter not polluted by implementation details +here Python, but any interpreter works + +architecture allows implementing features at the right level + +dynamic language enables defining our own various type systems +[ref pluggable type systems] + +practical VMs will result with a bit more efforts + +\end{document} From arigo at codespeak.net Tue May 30 18:45:07 2006 From: arigo at codespeak.net (arigo at codespeak.net) Date: Tue, 30 May 2006 18:45:07 +0200 (CEST) Subject: [pypy-svn] r27932 - pypy/extradoc/talk/dls2006 Message-ID: <20060530164507.05B201005A@code0.codespeak.net> Author: arigo Date: Tue May 30 18:45:05 2006 New Revision: 27932 Modified: pypy/extradoc/talk/dls2006/draft.txt Log: A very-last-promized check-in in draft.txt. Modified: pypy/extradoc/talk/dls2006/draft.txt ============================================================================== --- pypy/extradoc/talk/dls2006/draft.txt (original) +++ pypy/extradoc/talk/dls2006/draft.txt Tue May 30 18:45:05 2006 @@ -1169,7 +1169,9 @@ tool-chain itself - a one-time effort. Dynamic languages enable the definition of multiple custom type systems, -similar to *pluggable type systems* in Bracha_. This proved a key +similar to *pluggable type systems* in Bracha_ +but with simple type inference instead of explicit annotations. +This proved a key feature in implementing our translation tool-chain, because it makes a many-levels approach convenient: each abstraction level can provide an implementation for some of the features that the higher levels From arigo at codespeak.net Tue May 30 18:50:07 2006 From: arigo at codespeak.net (arigo at codespeak.net) Date: Tue, 30 May 2006 18:50:07 +0200 (CEST) Subject: [pypy-svn] r27933 - pypy/extradoc/talk/dls2006 Message-ID: <20060530165007.4FBA71005A@code0.codespeak.net> Author: arigo Date: Tue May 30 18:50:06 2006 New Revision: 27933 Modified: pypy/extradoc/talk/dls2006/paper.tex Log: Manual merge of r27925 to r27930 of draft.txt. At this point the two documents are in sync and only the .tex should be updated. Modified: pypy/extradoc/talk/dls2006/paper.tex ============================================================================== --- pypy/extradoc/talk/dls2006/paper.tex (original) +++ pypy/extradoc/talk/dls2006/paper.tex Tue May 30 18:50:06 2006 @@ -1057,80 +1057,106 @@ \section{Related work} \label{relatedwork} -Applying the expressiveness or at least syntax of very high-level and -dynamically typed languages to their implementation has been -investigated many times. -One typical approach is writing a static compiler. The viability of -and effort required for such an approach depend usually on the binding +Applying the expressiveness - or at least the syntax - of very +high-level and dynamically typed languages to their implementation has +been investigated many times. + +One typical approach is writing a static compiler. The viability of, +and effort required for, such an approach depends usually on the binding and dispatch semantics of the language. Common Lisp native compilers, -usable interactively and taking functions or files as compilation -units are a well-known example of that approach. Late binding for all -names and load semantics make such an approach very hard for Python, -if speed improvements are desired. - -It is more relevant to consider and compare with projects using -dynamic and very-high level languages for interpreters and VM -implementations, and Just-In-Time compilers. - -[Scheme48] was a Scheme implementation using a restricted Scheme, with -static type inference based on Hindley-Milner, this is viable for -Scheme as base language. Portability and simplicity were its major -goals. +usable interactively and taking single functions or files as compilation +units, are a well-known example of that approach. However, the late +binding for all names and the load semantics make such an approach very +hard for Python, if speed improvements are desired. + +In this context, it is more relevant to consider and compare with +projects using dynamic and very-high-level languages for interpreters +and VM implementations, and Just-In-Time compilers. + +Scheme48 was a Scheme implementation using a restricted Scheme, PreScheme +[PreScheme], with static type inference based on Hindley-Milner. This is +viable for Scheme as base language. Simplicity and portability across C +platforms were its major goals. -[Squeak] is a Smalltalk implementation in Smalltalk. It uses SLang, a +Squeak [Squeak] is a Smalltalk implementation in Smalltalk. It uses SLang, a very restricted subset of Smalltalk with few types and strict -conventions such that mostly direct translation to C is possible. -Both the VM and the object memory and garbage collector support are +conventions, which can be mostly directly translated to C. +The VM, the object memory and the garbage collector support are explicitly written together in this style. Again simplicity and -portability were the major goals, not sophisticated manipulation and -analysis and waving in of features. +portability were the major goals, as opposed to sophisticated manipulation +and analysis or "weaving" in of features as transformation aspects. -[Jikes RVM] is a Java VM and Just-In-Time compiler written in Java. +Jikes RVM [DBLP:journals/ibmsj/AlpernABBCCCFGHHLLMNRSSSSSSW00] is a +Java VM and Just-In-Time compiler written in Java. Bootstrapping happens by self-applying the compiler on a host VM, and dumping a snapshot from memory of the resulting native code. - -This approach enables directly high performance, at the price of -portability as usual with pure native code emitting +This approach directly enables high performance, at the price of +portability - as usual with pure native code emitting approaches. Modularity of features, when possible, is achieved with -normal software modularity. The indirection costs are taken care by -the inlining done by the compiler, sometimes even through explicit -ways to request for it. In particular this modular approach is used -for implementing a range of choices for GC support XXX ref. This was -the inspiration for PyPy own GC framework, although much more tuning -and work went into Jikes RVM. PyPy own GC framework also exploits +normal software modularity. The indirection costs are taken care of by +the compiler performing inlining (which is sometimes even explicitly +requested). In particular this modular approach is used +for implementing a range of choices for GC support [Jikes-GC]. This was +the inspiration for PyPy's own GC framework, although much more tuning +and work went into Jikes RVM. PyPy's own GC framework also exploits inlining of helpers and barriers to recover performance. -Jikes RVM native JIT compilers can likely not easily be retargeted to -run on top and target another VM (for example a CLR runtime) instead -of hardware processors. Also Jikes RVM pays the complexity of writing +Jikes RVM's native JIT compilers [Jikes-JIT] +are not meant to be retargetted to run in other environments +that hardware processors, for example in a CLR/.NET +runtime. Also Jikes RVM pays the complexity of writing a JIT up-front, which also means that features and semantics of the -language are encoded in the JIT compiler code, meaning likely that -major changes would correspond to major surgery needed on it. +language are encoded in the JIT compiler code. Major changes of the +language are likely to correspond to major surgery of the JIT. -PyPy more indirect approach, together hopefully with our future work +PyPy's more indirect approach, together hopefully with our future work on generating a JIT compiler, tries to overcome these limitations, at -the price of some more effort required to achieve very good -performance. It is too soon to compare completely the complexity (and -performance) trade-offs of these approaches. +the price of some more efforts required to achieve very good +performance. It is too soon for a complete comparison of the complexity, +performance and trade-offs of these approaches. -XXX Jython, IronPython, UVM. \section{Conclusion} \label{conclusion} -XXX - -nice interpreter not polluted by implementation details -here Python, but any interpreter works - -architecture allows implementing features at the right level - -dynamic language enables defining our own various type systems -[ref pluggable type systems] - -practical VMs will result with a bit more efforts +The PyPy project aims at showing that dynamic languages are suitable and +quite useful for writing virtual machines in. We believe that we have +achieved this objective. The present paper gave an overview of the +architecture that enabled this result. Experiments suggest that +practical virtual machines could reasonably follow in the near future, +with faster-than-current virtual machines with JIT specialization +techniques for the mid-term future. + +Targetting platforms that are very different from C/Posix is work in +progress, but given that many of the initial components are shared with +the existing stack of transformations leading to C, we are confident +that this work will soon give results. Moreover, we believe that these +results will show a reasonable efficiency, because the back-ends for VMs +like Squeak and .NET can take advantage of high-level input (as opposed +to trying to translate, say, C-like code to Smalltalk). + +A desirable property of our approach is to allow a given language and VM +to be specified only once, in the form of an interpreter. Moreover, the +interpreter can be kept simple (and thus keep its role as a +specification): not only is it written in a high-level language, but it +is not overloaded with low-level design choices and implementation +details. This makes language evolution and experimentation easier. +More generally, this property is important because many interpreters for +very difference languages can be written: the simpler these interpreters +can be kept, the more we win from our investment in writing the +tool-chain itself - a one-time effort. + +Dynamic languages enable the definition of multiple custom type systems, +similar to \textit{pluggable type systems} in [Bracha] but with simple +type inference instead of explicit annotations. This proved a key +feature in implementing our translation tool-chain, because it makes a +many-levels approach convenient: each abstraction level can provide an +implementation for some of the features that the higher levels +considered primitive. It offsets the need to define a minimal kernel of +primitives and build everything on top of it; instead, we have been able +to implement, so to speak, the right feature at the right level. \end{document} From pedronis at codespeak.net Tue May 30 18:58:22 2006 From: pedronis at codespeak.net (pedronis at codespeak.net) Date: Tue, 30 May 2006 18:58:22 +0200 (CEST) Subject: [pypy-svn] r27934 - pypy/extradoc/talk/dls2006 Message-ID: <20060530165822.1C6B010057@code0.codespeak.net> Author: pedronis Date: Tue May 30 18:58:21 2006 New Revision: 27934 Modified: pypy/extradoc/talk/dls2006/paper.tex Log: insert XXX as needed Modified: pypy/extradoc/talk/dls2006/paper.tex ============================================================================== --- pypy/extradoc/talk/dls2006/paper.tex (original) +++ pypy/extradoc/talk/dls2006/paper.tex Tue May 30 18:58:21 2006 @@ -37,7 +37,7 @@ such area. Building implementations of general programming languages, in particular highly dynamic ones, using a classic direct coding approach, is typically a long-winded effort and produces a result that -is quite [quite could be removed here?] tailored to a specific +is quite [XXX quite could be removed here?] tailored to a specific platform and where architectural decisions (e.g. about GC) are spread across the code in a pervasive and invasive way. @@ -211,10 +211,10 @@ We have implemented other transformations as well, e.g. performing various optimizations, or turning the whole code into a -continuation-passing style (CPS) [I'm not sure our transformation +continuation-passing style (CPS) [XXX I'm not sure our transformation can be classified as classical CPS, although there are known similar techniques but the terminology is quite confused] that allows us to use coroutines without giving up the ability to generate fully ANSI C code. (This will -be the subject of another paper.) [mention exception transformer too] +be the subject of another paper.) [XXX mention exception transformer too] Finally, currently under development is a variant of the very first transformation step, for use when targeting higher-level, @@ -296,7 +296,7 @@ written in plain Python, and it manipulates "objects" that are still at a lower level: pointer and address objects. Even with the restriction of having to use pointer-like and address-like objects, Python remains -more expressive than, say, C to write a GC. [see also Jikes] +more expressive than, say, C to write a GC. [XXX see also Jikes] In the sequel, we will call \textit{system code} functions written in Python that are meant to be analysed by the front-end. For the From arigo at codespeak.net Tue May 30 19:32:10 2006 From: arigo at codespeak.net (arigo at codespeak.net) Date: Tue, 30 May 2006 19:32:10 +0200 (CEST) Subject: [pypy-svn] r27937 - pypy/extradoc/talk/dls2006 Message-ID: <20060530173210.F328610036@code0.codespeak.net> Author: arigo Date: Tue May 30 19:32:08 2006 New Revision: 27937 Modified: pypy/extradoc/talk/dls2006/paper.tex Log: Filling in numbers, and trying to explain them. Modified: pypy/extradoc/talk/dls2006/paper.tex ============================================================================== --- pypy/extradoc/talk/dls2006/paper.tex (original) +++ pypy/extradoc/talk/dls2006/paper.tex Tue May 30 19:32:08 2006 @@ -865,7 +865,7 @@ Our tool-chain is capable of translating the Python interpreter of PyPy, written in RPython, producing right now either ANSI C code as -described before, or LLVM\footnote{the LLVM project is the realisation +described before, or LLVM\footnote{The LLVM project is the realisation of a portable assembler infrastructure, offering both a virtual machine with JIT capabilities and static compilation. Currently we are using the latter with its good high-level optimisations for PyPy.} @@ -889,11 +889,11 @@ +------------------------------------+-------------------+-------------------+ | pypy-c-thread | 4552ms (5.8x) | 7122 (5.7x) | +------------------------------------+-------------------+-------------------+ -| pypy-c-stackless | XXX (6.0x) | XXX (6.2x) | +| pypy-c-stackless | 5121ms (6.5x) | 6060 (6.7x) | +------------------------------------+-------------------+-------------------+ | pypy-c-gcframework | 6327ms (8.0x) | 4960 (8.1x) | +------------------------------------+-------------------+-------------------+ -| pypy-c-stackless-gcframework | XXX ( ) | XXX ( ) | +| pypy-c-stackless-gcframework | 8743ms (11.0x) | 3755 (10.7x) | +------------------------------------+-------------------+-------------------+ | pypy-llvm-c | 3797ms (4.8x) | 7763 (5.2x) | +------------------------------------+-------------------+-------------------+ @@ -933,12 +933,14 @@ pypy-c-stackless-gcframework This variant combines the "gc transformation" step with the "stackless transformation" step. The overhead introduced by the - stackless feature is balanced with the removal of the overhead of - pushing and popping roots explicitly on an alternate stack: indeed, - in this variant it is possible to ask the functions in the current C - call chain to save their local state and return. This has the - side-effect of moving all roots to the heap, where the GC can find - them. + stackless feature is theoretically balanced with the removal of the + overhead of pushing and popping roots explicitly on an alternate + stack: indeed, in this variant it is possible to ask the functions + in the current C call chain to save their local state and return. + This has the side-effect of moving all roots to the heap, where the + GC can find them. (We hypothesize that the large slowdown is caused + by the extreme size of the executable in this case - 21MB, compared to + 6MB for the basic pypy-c. Making it smaller is work in progress.) pypy-llvm-c The same as pypy-c, but using the LLVM back-end instead of the C @@ -1007,7 +1009,7 @@ speculate it is because of the increase in size caused by the previous transformations). A translation of pypy-c-stackless, without counting GCC time, takes 60 minutes; the same for pypy-c-stackless-gcframework -takes XXX minutes. +takes 129 minutes. From arigo at codespeak.net Tue May 30 19:39:44 2006 From: arigo at codespeak.net (arigo at codespeak.net) Date: Tue, 30 May 2006 19:39:44 +0200 (CEST) Subject: [pypy-svn] r27938 - pypy/extradoc/talk/dls2006 Message-ID: <20060530173944.5134F1005A@code0.codespeak.net> Author: arigo Date: Tue May 30 19:39:42 2006 New Revision: 27938 Modified: pypy/extradoc/talk/dls2006/paper.tex Log: Minor latexifications. Modified: pypy/extradoc/talk/dls2006/paper.tex ============================================================================== --- pypy/extradoc/talk/dls2006/paper.tex (original) +++ pypy/extradoc/talk/dls2006/paper.tex Tue May 30 19:39:42 2006 @@ -908,21 +908,21 @@ cache. The rows correspond to variants of the translation process, as follows: -pypy-c +{\bf pypy-c.} The simplest variant: translated to C code with no explicit memory management, and linked with the Boehm conservative GC [Boehm]. -pypy-c-thread +{\bf pypy-c-thread.} The same, with OS thread support enabled. (For measurement purposes, thread support is kept separate because it has an impact on the GC performance.) -pypy-c-stackless +{\bf pypy-c-stackless.} The same as pypy-c, plus the "stackless transformation" step which modifies the flow graph of all functions in a way that allows them to save and restore their local state, as a way to enable coroutines. -pypy-c-gcframework +{\bf pypy-c-gcframework.} In this variant, the "gc transformation" step inserts explicit memory management and a simple mark-and-sweep GC implementation. The resulting program is not linked with Boehm. Note that it is not @@ -930,7 +930,7 @@ in this variant each function explicitly pushes and pops all roots to an alternate stack around each subcall. -pypy-c-stackless-gcframework +{\bf pypy-c-stackless-gcframework.} This variant combines the "gc transformation" step with the "stackless transformation" step. The overhead introduced by the stackless feature is theoretically balanced with the removal of the @@ -942,13 +942,13 @@ by the extreme size of the executable in this case - 21MB, compared to 6MB for the basic pypy-c. Making it smaller is work in progress.) -pypy-llvm-c +{\bf pypy-llvm-c.} The same as pypy-c, but using the LLVM back-end instead of the C back-end. The LLVM assembler-compiler gives the best results when - as we do here -- it optimizes its input and generates again C code, which is fed to GCC. -pypy-llvm-c-prof +{\bf pypy-llvm-c-prof.} The same as pypy-llvm-c, but using GCC's profile-driven optimizations. @@ -959,7 +959,7 @@ dominant, factor is that various indices show that our approach places a very high load on the GC and on the memory caches of the machine. The Boehm GC is known to be less efficient than more customized approach; -kernel-level profiling shows that pypy-c typically spends 30% of its +kernel-level profiling shows that pypy-c typically spends 30\% of its time in the Boehm library. Our current, naively simple mark-and-sweep GC is even quite worse. The interaction with processor caches is also hard to predict and account for; in general, we tend to produce From fijal at codespeak.net Wed May 31 00:25:11 2006 From: fijal at codespeak.net (fijal at codespeak.net) Date: Wed, 31 May 2006 00:25:11 +0200 (CEST) Subject: [pypy-svn] r27945 - in pypy/dist/pypy/translator/js2: . test Message-ID: <20060530222511.E072510057@code0.codespeak.net> Author: fijal Date: Wed May 31 00:25:09 2006 New Revision: 27945 Modified: pypy/dist/pypy/translator/js2/database.py pypy/dist/pypy/translator/js2/test/test_class.py Log: Bugfix for failing test. Modified: pypy/dist/pypy/translator/js2/database.py ============================================================================== --- pypy/dist/pypy/translator/js2/database.py (original) +++ pypy/dist/pypy/translator/js2/database.py Wed May 31 00:25:09 2006 @@ -90,7 +90,10 @@ return None const = AbstractConst.make(self, value) try: - return self.consts[const] + if retval == 'name': + return self.consts[const] + else: + return const except KeyError: log("New const:%r"%value) if isinstance(value, ootype._string): @@ -120,7 +123,6 @@ def generate_constants(consts): all_c = [const for const,name in consts.iteritems()] rendered = set() - while len(all_c) > 0: const = all_c.pop() if const not in rendered: Modified: pypy/dist/pypy/translator/js2/test/test_class.py ============================================================================== --- pypy/dist/pypy/translator/js2/test/test_class.py (original) +++ pypy/dist/pypy/translator/js2/test/test_class.py Wed May 31 00:25:09 2006 @@ -87,7 +87,7 @@ assert f(False) == llvmsnippet.call_degrading_func(False) def test_circular_classdef(self): - py.test.skip("Problems with constant names") + #py.test.skip("Problems with constant names") #py.test.skip("Inheritance not implemented") f = compile_function(llvmsnippet.circular_classdef, []) assert f() == 10 From ale at codespeak.net Wed May 31 10:01:24 2006 From: ale at codespeak.net (ale at codespeak.net) Date: Wed, 31 May 2006 10:01:24 +0200 (CEST) Subject: [pypy-svn] r27950 - pypy/dist/pypy/doc Message-ID: <20060531080124.0426A10053@code0.codespeak.net> Author: ale Date: Wed May 31 10:01:23 2006 New Revision: 27950 Modified: pypy/dist/pypy/doc/events.txt pypy/dist/pypy/doc/news.txt Log: Fix links Modified: pypy/dist/pypy/doc/events.txt ============================================================================== --- pypy/dist/pypy/doc/events.txt (original) +++ pypy/dist/pypy/doc/events.txt Wed May 31 10:01:23 2006 @@ -40,9 +40,9 @@ Once again a PyPy sprint will take place right after the EuroPython Conference. This year it will be from the *6th to the 9th of July*. -Read more in `the sprint announcement`_, see who is planning to attend -on the `people page`_. There is also a page_ in the python wiki. +Read more in `EuroPython sprint announcement`_, see who is planning to attend +on `the people page`_. There is also a page_ in the python wiki. -.. _`the sprint announcement`: http://codespeak.net/pypy/extradoc/sprintinfo/europython-2006/announce.html -.. _`people page`: http://codespeak.net/pypy/extradoc/sprintinfo/europython-2006/people.html +.. _`EuroPython sprint announcement`: http://codespeak.net/pypy/extradoc/sprintinfo/europython-2006/announce.html +.. _`the people page`: http://codespeak.net/pypy/extradoc/sprintinfo/europython-2006/people.html .. _page: http://wiki.python.org/moin/EuroPython2006 Modified: pypy/dist/pypy/doc/news.txt ============================================================================== --- pypy/dist/pypy/doc/news.txt (original) +++ pypy/dist/pypy/doc/news.txt Wed May 31 10:01:23 2006 @@ -209,14 +209,14 @@ to a low level language and reaching 2.4.1 Python compliance. The goal of the sprint is to release a first self-contained PyPy-0.7 version. Carl has written a report about `day 1 - 3`_, -there are some pictures_ online and a `heidelberg summary report`_ +there are `some pictures`_ online and a `heidelberg summary report`_ detailing some of the works that led to the successful release of `pypy-0.7.0`_! .. _`heidelberg summary report`: http://codespeak.net/pypy/extradoc/sprintinfo/Heidelberg-report.html .. _`PyPy sprint`: http://codespeak.net/pypy/extradoc/sprintinfo/Heidelberg-sprint.html .. _`day 1 - 3`: http://codespeak.net/pipermail/pypy-dev/2005q3/002287.html -.. _pictures: http://codespeak.net/~hpk/heidelberg-sprint/ +.. _`some pictures`: http://codespeak.net/~hpk/heidelberg-sprint/ PyPy Hildesheim2 finished: first self-contained PyPy run! =========================================================== From arigo at codespeak.net Wed May 31 10:55:34 2006 From: arigo at codespeak.net (arigo at codespeak.net) Date: Wed, 31 May 2006 10:55:34 +0200 (CEST) Subject: [pypy-svn] r27953 - in pypy/dist/pypy/rpython: . memory Message-ID: <20060531085534.D01D310053@code0.codespeak.net> Author: arigo Date: Wed May 31 10:55:33 2006 New Revision: 27953 Modified: pypy/dist/pypy/rpython/annlowlevel.py pypy/dist/pypy/rpython/memory/gctransform.py Log: Fix a gc=ref bug: a DelayedPointer seen by the exception transformer because the ll_incref/decref functions are still delayed. Couldn't find an example smaller than PyPy that triggers it, sadly. Also, trying to inline the incref/decrefs. This gives a 3x speed-up on richards. Modified: pypy/dist/pypy/rpython/annlowlevel.py ============================================================================== --- pypy/dist/pypy/rpython/annlowlevel.py (original) +++ pypy/dist/pypy/rpython/annlowlevel.py Wed May 31 10:55:33 2006 @@ -215,6 +215,7 @@ "originally specified: %r\n" " found by annotating: %r" % (graph, s_result, s_real_result)) + del self.pending[:] def finish_rtype(self): rtyper = self.rtyper @@ -228,13 +229,14 @@ lltype.typeOf(p).TO.become(lltype.typeOf(real_p).TO) p._become(real_p) rtyper.specialize_more_blocks() - del self.pending[:] del self.delayedreprs[:] del self.delayedconsts[:] + del self.delayedfuncs[:] def backend_optimize(self, **flags): # only optimize the newly created graphs from pypy.translator.backendopt.all import backend_optimizations translator = self.rtyper.annotator.translator newgraphs = translator.graphs[self.original_graph_count:] + self.original_graph_count = len(translator.graphs) backend_optimizations(translator, newgraphs, **flags) Modified: pypy/dist/pypy/rpython/memory/gctransform.py ============================================================================== --- pypy/dist/pypy/rpython/memory/gctransform.py (original) +++ pypy/dist/pypy/rpython/memory/gctransform.py Wed May 31 10:55:33 2006 @@ -264,17 +264,19 @@ def replace_safe_call(self, op, livevars, block): return [SpaceOperation("direct_call", op.args, op.result)] - def annotate_helper(self, ll_helper, ll_args, ll_result): + def annotate_helper(self, ll_helper, ll_args, ll_result, inline=False): assert not self.finished_helpers args_s = map(annmodel.lltype_to_annotation, ll_args) s_result = annmodel.lltype_to_annotation(ll_result) graph = self.mixlevelannotator.getgraph(ll_helper, args_s, s_result) # the produced graphs does not need to be fully transformed self.need_minimal_transform(graph) + if inline: + self.graphs_to_inline[graph] = True return self.mixlevelannotator.graph2delayed(graph) def inittime_helper(self, ll_helper, ll_args, ll_result): - ptr = self.annotate_helper(ll_helper, ll_args, ll_result) + ptr = self.annotate_helper(ll_helper, ll_args, ll_result, inline=True) return Constant(ptr, lltype.typeOf(ptr)) def finish_helpers(self): @@ -407,7 +409,7 @@ HDR = lltype.Struct("header", ("refcount", lltype.Signed)) def __init__(self, translator): - super(RefcountingGCTransformer, self).__init__(translator) + super(RefcountingGCTransformer, self).__init__(translator, inline=True) self.gcheaderbuilder = GCHeaderBuilder(self.HDR) gc_header_offset = self.gcheaderbuilder.size_gc_header self.deallocator_graphs_needing_transforming = [] @@ -423,6 +425,14 @@ gcheader.signed[0] = refcount if refcount == 0: dealloc(adr) + def ll_decref_simple(adr): + if adr: + gcheader = adr - gc_header_offset + refcount = gcheader.signed[0] - 1 + if refcount == 0: + llop.gc_free(lltype.Void, adr) + else: + gcheader.signed[0] = refcount def ll_no_pointer_dealloc(adr): llop.gc_free(lltype.Void, adr) if self.translator: @@ -431,8 +441,11 @@ self.decref_ptr = self.inittime_helper( ll_decref, [llmemory.Address, lltype.Ptr(ADDRESS_VOID_FUNC)], lltype.Void) + self.decref_simple_ptr = self.inittime_helper( + ll_decref_simple, [llmemory.Address], lltype.Void) self.no_pointer_dealloc_ptr = self.inittime_helper( ll_no_pointer_dealloc, [llmemory.Address], lltype.Void) + self.mixlevelannotator.finish() # for now # cache graphs: self.decref_funcptrs = {} self.static_deallocator_funcptrs = {} @@ -453,12 +466,17 @@ result = [SpaceOperation("cast_ptr_to_adr", [var], adr1)] dealloc_fptr = self.dynamic_deallocation_funcptr_for_type(PTRTYPE.TO) - cdealloc_fptr = rmodel.inputconst( - lltype.typeOf(dealloc_fptr), dealloc_fptr) - - result.append(SpaceOperation("direct_call", - [self.decref_ptr, adr1, cdealloc_fptr], - varoftype(lltype.Void))) + if dealloc_fptr is self.no_pointer_dealloc_ptr.value: + # simple case + result.append(SpaceOperation("direct_call", + [self.decref_simple_ptr, adr1], + varoftype(lltype.Void))) + else: + cdealloc_fptr = rmodel.inputconst( + lltype.typeOf(dealloc_fptr), dealloc_fptr) + result.append(SpaceOperation("direct_call", + [self.decref_ptr, adr1, cdealloc_fptr], + varoftype(lltype.Void))) return result def replace_gc_protect(self, op, livevars, block): From arigo at codespeak.net Wed May 31 11:32:31 2006 From: arigo at codespeak.net (arigo at codespeak.net) Date: Wed, 31 May 2006 11:32:31 +0200 (CEST) Subject: [pypy-svn] r27954 - pypy/extradoc/talk/dls2006 Message-ID: <20060531093231.429A510036@code0.codespeak.net> Author: arigo Date: Wed May 31 11:32:30 2006 New Revision: 27954 Modified: pypy/extradoc/talk/dls2006/paper.tex Log: Fix figure 1. Modified: pypy/extradoc/talk/dls2006/paper.tex ============================================================================== --- pypy/extradoc/talk/dls2006/paper.tex (original) +++ pypy/extradoc/talk/dls2006/paper.tex Wed May 31 11:32:30 2006 @@ -113,7 +113,7 @@ in [S]. -\section{System programming with Python} +\section{System programming in Python} \label{systemprog} \hypertarget{the-translation-process}{} @@ -254,29 +254,15 @@ transformation step also needs to insert new functions into the forest. A key feature of our approach is that we can write such "system-level" code -- relevant only to a particular transformation -- in plain Python -as well: +as well. The idea is to feed these new Python functions into the +front-end, using this time the transformation's target (lower-level) +type system during the type inference. In other words, we can write +plain Python code that manipulates objects that conform to the +lower-level type system, and have these functions automatically +transformed into appropriately typed graphs. -\begin{verbatim} -.. topic:: Figure 1 - a helper to implement \texttt{list.append()} - - :: - - def ll_append(lst, newitem): - # Append an item to the end of the vector. - index = lst.length # get the 'length' field - ll_resize(lst, index+1) # call a helper not shown here - itemsarray = lst.items # get the 'items' field - itemsarray[index] = item # this behaves like a C array -\end{verbatim} - -The idea is to feed these new Python functions into the front-end, using -this time the transformation's target (lower-level) type system during -the type inference. In other words, we can write plain Python code that -manipulates objects that conform to the lower-level type system, and -have these functions automatically transformed into appropriately typed -graphs. - -For example, \texttt{ll\textunderscore{}append()} in figure 1 is a Python function +For example, \texttt{ll\textunderscore{}append()} in figure \ref{llappend} +is a Python function that manipulates objects that behave like C structures and arrays. This function is inserted by the LLTyper, as a helper to implement the \texttt{list.append()} calls found in its RPython-level input graphs. @@ -290,6 +276,19 @@ indistinguishable from the other graphs of the forest produced by the LLTyper. +\begin{figure} +\begin{verbatim} +def ll_append(lst, newitem): + # Append an item to the end of the vector. + index = lst.length # get the 'length' field + ll_resize(lst, index+1) # call another helper + itemsarray = lst.items # get the 'items' field + itemsarray[index] = item # behaves like a C array +\end{verbatim} +\caption{A helper to implement \texttt{list.append()}.} +\label{llappend} +\end{figure} + In the example of the \texttt{malloc} operation, replaced by a call to GC code, this GC code can invoke a complete collection of dead objects, and can thus be arbitrarily complicated. Still, our GC code is entirely @@ -939,7 +938,7 @@ in the current C call chain to save their local state and return. This has the side-effect of moving all roots to the heap, where the GC can find them. (We hypothesize that the large slowdown is caused - by the extreme size of the executable in this case - 21MB, compared to + by the extreme size of the executable in this case -- 21MB, compared to 6MB for the basic pypy-c. Making it smaller is work in progress.) {\bf pypy-llvm-c.} @@ -1060,7 +1059,7 @@ \label{relatedwork} -Applying the expressiveness - or at least the syntax - of very +Applying the expressiveness -- or at least the syntax -- of very high-level and dynamically typed languages to their implementation has been investigated many times. @@ -1094,7 +1093,7 @@ Bootstrapping happens by self-applying the compiler on a host VM, and dumping a snapshot from memory of the resulting native code. This approach directly enables high performance, at the price of -portability - as usual with pure native code emitting +portability -- as usual with pure native code emitting approaches. Modularity of features, when possible, is achieved with normal software modularity. The indirection costs are taken care of by the compiler performing inlining (which is sometimes even explicitly @@ -1149,7 +1148,7 @@ More generally, this property is important because many interpreters for very difference languages can be written: the simpler these interpreters can be kept, the more we win from our investment in writing the -tool-chain itself - a one-time effort. +tool-chain itself -- a one-time effort. Dynamic languages enable the definition of multiple custom type systems, similar to \textit{pluggable type systems} in [Bracha] but with simple From mwh at codespeak.net Wed May 31 11:39:00 2006 From: mwh at codespeak.net (mwh at codespeak.net) Date: Wed, 31 May 2006 11:39:00 +0200 (CEST) Subject: [pypy-svn] r27955 - pypy/extradoc/talk/dls2006 Message-ID: <20060531093900.825C51005A@code0.codespeak.net> Author: mwh Date: Wed May 31 11:38:59 2006 New Revision: 27955 Modified: pypy/extradoc/talk/dls2006/paper.tex Log: latexify tables. Modified: pypy/extradoc/talk/dls2006/paper.tex ============================================================================== --- pypy/extradoc/talk/dls2006/paper.tex (original) +++ pypy/extradoc/talk/dls2006/paper.tex Wed May 31 11:38:59 2006 @@ -460,19 +460,18 @@ The actual transformation from function objects -- i.e. bytecode -- to flow graph is performed by the Flow Object Space, a short but generic plug-in component for the Python interpreter of PyPy. The architecture -of our Python interpreter is shown in figure 4. +of our Python interpreter is shown in figure \ref{interpobjspace}. -\begin{verbatim} -.. topic:: Figure 4 - the interpreter and object spaces - - +------------------------------------------------------+ - | forest of bytecode objects from the application | - +------------------------------------------------------+ - | Python bytecode interpreter | - +--------------------------------+---------------------+ - | Standard Object Space | Flow Object Space | - +--------------------------------+---------------------+ -\end{verbatim} +\begin{figure} + \centering + \caption{the interpreter and object spaces} + \label{interpobjspace} + \begin{tabular}{|c|c|} \hline +\multicolumn{2}{|c|}{forest of bytecode objects from the application} \\ \hline +\multicolumn{2}{|c|}{Python bytecode interpreter} \\ \hline + Standard Object Space & Flow Object Space \\ \hline + \end{tabular} +\end{figure} Note that the left column, i.e. the bytecode interpreter and the Standard Object Space, form the full Python interpreter of PyPy. It is @@ -873,32 +872,30 @@ The tool-chain has been tested with and can sucessfully apply transformations enabling various combinations of features. The translated interpreters are benchmarked using pystone (a [Dhrystone] -derivative traditionally used by the Python community, although it is a -rather poor benchmark) and the classical [Richards] benchmark and -compared against [CPython] 2.4.3 results: - -\begin{verbatim} -+------------------------------------+-------------------+-------------------+ -| Interpreter | Richards, | Pystone, | -| | Time/iteration | Iterations/second | -+====================================+===================+===================+ -| CPython 2.4.3 | 789ms (1.0x) | 40322 (1.0x) | -+------------------------------------+-------------------+-------------------+ -| pypy-c | 4269ms (5.4x) | 7587 (5.3x) | -+------------------------------------+-------------------+-------------------+ -| pypy-c-thread | 4552ms (5.8x) | 7122 (5.7x) | -+------------------------------------+-------------------+-------------------+ -| pypy-c-stackless | 5121ms (6.5x) | 6060 (6.7x) | -+------------------------------------+-------------------+-------------------+ -| pypy-c-gcframework | 6327ms (8.0x) | 4960 (8.1x) | -+------------------------------------+-------------------+-------------------+ -| pypy-c-stackless-gcframework | 8743ms (11.0x) | 3755 (10.7x) | -+------------------------------------+-------------------+-------------------+ -| pypy-llvm-c | 3797ms (4.8x) | 7763 (5.2x) | -+------------------------------------+-------------------+-------------------+ -| pypy-llvm-c-prof | 2772ms (3.5x) | 10245 (3.9x) | -+------------------------------------+-------------------+-------------------+ -\end{verbatim} +derivative traditionally used by the Python community, although it is +a rather poor benchmark) and the classical [Richards] benchmark and +compared against [CPython] 2.4.3 results and are summarized in table +\ref{perfsumm}. + +\begin{table*} +% the layout of this table isn't wonderful, but it's probably OK. +\centering +\caption{Summary of interpreter performance} +\label{perfsumm} +\begin{tabular}{|l|c|c|} \hline +\textbf{Interpreter} & +\textbf{Richards, Time/iteration} & +\textbf{Pystone, Iterations/second} \\ \hline +CPython 2.4.3 & 789ms (1.0x) & 40322 (1.0x) \\ \hline +pypy-c & 4269ms (5.4x) & 7587 (5.3x) \\ \hline +pypy-c-thread & 4552ms (5.8x) & 7122 (5.7x) \\ \hline +pypy-c-stackless & 5121ms (6.5x) & 6060 (6.7x) \\ \hline +pypy-c-gcframework & 6327ms (8.0x) & 4960 (8.1x) \\ \hline +pypy-c-stackless-gcframework & 8743ms (11.0x) & 3755 (10.7x) \\ \hline +pypy-llvm-c & 3797ms (4.8x) & 7763 (5.2x) \\ \hline +pypy-llvm-c-prof & 2772ms (3.5x) & 10245 (3.9x) \\ \hline +\end{tabular} +\end{table*} The numbers in parenthesis are slow-down factors compared to CPython. These measures reflect PyPy revision 27815, compiled with GCC 3.4.4. @@ -968,34 +965,37 @@ \subsection{Translation times} A complete translation of the pypy-c variant takes about 39 minutes, -divided as follows: +divided as shown in table \ref{translationtimes}. -\begin{verbatim} -+-------------------------------------------+------------------------------+ -| Step | Time (minutes:seconds) | -+===========================================+==============================+ -| Front-end | 9:01 | -| (flow graphs and type inference) | | -+-------------------------------------------+------------------------------+ -| LLTyper | 10:38 | -| (from RPython-level to C-level graphs | | -| and data) | | -+-------------------------------------------+------------------------------+ -| Various low-level optimizations | 6:51 | -| (convert some heap allocations to local | | -| variables, inlining, ...) | | -+-------------------------------------------+------------------------------+ -| Database building | 8:39 | -| (this initial back-end step follows all | | -| graphs and prebuilt data structures | | -| recursively, assigns names, and orders | | -| them suitably for code generation) | | -+-------------------------------------------+------------------------------+ -| Generating C source | 2:25 | -+-------------------------------------------+------------------------------+ -| Compiling (\texttt{gcc -O2}) | 3:23 | -+-------------------------------------------+------------------------------+ -\end{verbatim} +\begin{table*} +\centering +\caption{Dividing overall translation time by stage} +\label{translationtimes} +\begin{tabular}{|p{0.65\linewidth}|c|} \hline +\textbf{Step} & \textbf{Time (minutes:seconds)} \\ \hline +Front-end +(flow graphs and type inference) +& 9:01 \\ \hline +LLTyper +(from RPython-level to C-level graphs +and data) +& 10:38 \\ \hline +Various low-level optimizations +(convert some heap allocations to local +variables, inlining, ...) +& 6:51 \\ \hline +Database building +(this initial back-end step follows all +graphs and prebuilt data structures +recursively, assigns names, and orders +them suitably for code generation) +& 8:39 \\ \hline +Generating C source +& 2:25 \\ \hline +Compiling (\texttt{gcc -O2}) +& 3:23 \\ \hline +\end{tabular} +\end{table*} An interesting feature of this table is that type inference is not the bottleneck. Indeed, further transformation steps typically take longer From arigo at codespeak.net Wed May 31 11:39:39 2006 From: arigo at codespeak.net (arigo at codespeak.net) Date: Wed, 31 May 2006 11:39:39 +0200 (CEST) Subject: [pypy-svn] r27956 - pypy/extradoc/talk/dls2006 Message-ID: <20060531093939.D4DE710063@code0.codespeak.net> Author: arigo Date: Wed May 31 11:39:38 2006 New Revision: 27956 Modified: pypy/extradoc/talk/dls2006/paper.tex Log: Next figure. Modified: pypy/extradoc/talk/dls2006/paper.tex ============================================================================== --- pypy/extradoc/talk/dls2006/paper.tex (original) +++ pypy/extradoc/talk/dls2006/paper.tex Wed May 31 11:39:38 2006 @@ -88,7 +88,7 @@ \label{architecture} There are two major components in PyPy: - +% \begin{enumerate} \item the \textit{Standard Interpreter}: an implementation of the Python programming language, mostly complete and compliant with the current version of the @@ -96,7 +96,7 @@ \item the \textit{Translation Process}: a translation tool-suite whose goal is to compile subsets of Python to various environment. \end{enumerate} - +% In particular, we have defined a subset of the Python language called "restricted Python" or RPython. This sublanguage is not restricted syntactically, but only in the way it manipulates objects of different @@ -140,7 +140,7 @@ then a stack of transformations ] \end{verbatim} - +% \begin{enumerate} \item We take as input RPython functions\footnote{The input to our translation chain are indeed loaded runtime function objects, @@ -165,7 +165,7 @@ graphs. This type inference process is described in more details in section \ref{typeinference}. \end{enumerate} - + % At the end of the front-end analysis, the input RPython program is represented as a forest of flow graphs with typed variables. Following this analysis are a number of transformation steps. Each transformation @@ -261,7 +261,7 @@ lower-level type system, and have these functions automatically transformed into appropriately typed graphs. -For example, \texttt{ll\textunderscore{}append()} in figure \ref{llappend} +For example, \texttt{ll\textunderscore{}append()} in figure \ref{fig_llappend} is a Python function that manipulates objects that behave like C structures and arrays. This function is inserted by the LLTyper, as a helper to implement the @@ -286,7 +286,7 @@ itemsarray[index] = item # behaves like a C array \end{verbatim} \caption{A helper to implement \texttt{list.append()}.} -\label{llappend} +\label{fig_llappend} \end{figure} In the example of the \texttt{malloc} operation, replaced by a call to GC @@ -327,20 +327,20 @@ \subsection{Type systems} -The four levels that we considered so far are summarized in figure 2. +The four levels that we considered so far are summarized in figure +\ref{fig_typesystems}. +\begin{figure} \begin{verbatim} -:: - - [figure 2: RPython - / \ - / \ - LLTypeSystem OOTypeSystem - / - / - Raw addresses - ] + RPython + / \ + LLTypeSystem OOTypeSystem + / + Raw addresses \end{verbatim} +\caption{Type systems, informally ordered by abstraction level} +\label{fig_typesystems} +\end{figure} The RPython level is a subset of Python, so the types mostly follow Python types, and the instances of these types are instances in the @@ -351,7 +351,7 @@ The other type systems, however, do not correspond to built-in Python types. For each of them, we implemented: - +% \begin{enumerate} \item the types, which we use to tag the variables of the graphs at the given level. (Types are actually annotated, self-recursive @@ -361,12 +361,12 @@ \item the Python objects that emulate instances of these types. (More about them below.) \end{enumerate} - +% We have defined well-typed operations between variables of these types, plugging on the standard Python operators. These operations are the ones that the emulating instances implement. As seen above, the types can also be used by type inference when analysing system code like the -helpers of figure 1. +helpers of figure \ref{fig_llappend}. Now, clearly, the purpose of types like a "C-like struct" or a "C-like array" is to be translated to a real \texttt{struct} or array declaration by @@ -637,7 +637,7 @@ RPython types. The set $A$ of RPython types is defined as the following formal terms: - +% \begin{itemize} \item $Bot$, $Top$ -- the minimum and maximum elements (corresponding to "impossible value" and "most general value"); @@ -664,7 +664,7 @@ \item $NullableStr$, $NullableInst(class)$ -- a string or \texttt{None}; resp. an instance or \texttt{None}. \end{itemize} - +% Figures 6 and 7 shows how these types are ordered to form a lattice. We mostly use its structure of [join-semilattice] only. From arigo at codespeak.net Wed May 31 11:48:04 2006 From: arigo at codespeak.net (arigo at codespeak.net) Date: Wed, 31 May 2006 11:48:04 +0200 (CEST) Subject: [pypy-svn] r27957 - pypy/extradoc/talk/dls2006 Message-ID: <20060531094804.4E91B10060@code0.codespeak.net> Author: arigo Date: Wed May 31 11:48:03 2006 New Revision: 27957 Modified: pypy/extradoc/talk/dls2006/paper.tex Log: Verbatimized. Modified: pypy/extradoc/talk/dls2006/paper.tex ============================================================================== --- pypy/extradoc/talk/dls2006/paper.tex (original) +++ pypy/extradoc/talk/dls2006/paper.tex Wed May 31 11:48:03 2006 @@ -771,12 +771,14 @@ precise enough information for our needs. We must describe a detail of the abstract interpretation engine that is critical for precision: the propagation of conditional types. Consider the following source code -fragment:: +fragment: +\begin{verbatim} if isinstance(x, MyClass): f(x) else: g(x) +\end{verbatim} Although the type of \texttt{x} may be some parent class of \texttt{MyClass}, it can be deduced to be of the more precise type From arigo at codespeak.net Wed May 31 12:04:44 2006 From: arigo at codespeak.net (arigo at codespeak.net) Date: Wed, 31 May 2006 12:04:44 +0200 (CEST) Subject: [pypy-svn] r27958 - pypy/extradoc/talk/dls2006/image Message-ID: <20060531100444.D7BC010036@code0.codespeak.net> Author: arigo Date: Wed May 31 12:04:39 2006 New Revision: 27958 Added: pypy/extradoc/talk/dls2006/image/lattice1.pdf (contents, props changed) pypy/extradoc/talk/dls2006/image/lattice2.pdf (contents, props changed) Log: PDF versions of lattice*.dot. Added: pypy/extradoc/talk/dls2006/image/lattice1.pdf ============================================================================== Binary file. No diff available. Added: pypy/extradoc/talk/dls2006/image/lattice2.pdf ============================================================================== Binary file. No diff available. From arigo at codespeak.net Wed May 31 12:06:59 2006 From: arigo at codespeak.net (arigo at codespeak.net) Date: Wed, 31 May 2006 12:06:59 +0200 (CEST) Subject: [pypy-svn] r27959 - pypy/extradoc/talk/dls2006 Message-ID: <20060531100659.B8EE410036@code0.codespeak.net> Author: arigo Date: Wed May 31 12:06:55 2006 New Revision: 27959 Modified: pypy/extradoc/talk/dls2006/paper.tex Log: Adding a bit of text, and fixing e.g. => e.g.\ Modified: pypy/extradoc/talk/dls2006/paper.tex ============================================================================== --- pypy/extradoc/talk/dls2006/paper.tex (original) +++ pypy/extradoc/talk/dls2006/paper.tex Wed May 31 12:06:55 2006 @@ -37,8 +37,8 @@ such area. Building implementations of general programming languages, in particular highly dynamic ones, using a classic direct coding approach, is typically a long-winded effort and produces a result that -is quite [XXX quite could be removed here?] tailored to a specific -platform and where architectural decisions (e.g. about GC) are spread +is tailored to a specific +platform and where architectural decisions (e.g.\ about GC) are spread across the code in a pervasive and invasive way. For this and other reasons, standard platforms emerge; nowadays, a @@ -159,7 +159,7 @@ stage, types inferred are part of the type system which is the very definition of the RPython sub-language: they are roughly a subset of Python's built-in types, with some more precision to - describe e.g. the items stored in container types. + describe e.g.\ the items stored in container types. Occasionally, a single input function can produce several specialized versions, i.e. several similar but differently typed graphs. This type inference process is described in more @@ -173,7 +173,7 @@ the operations they contain. Each step inputs graphs typed in one type system and leaves them typed in a possibly different type system, as we will describe in the sequel. Finally, a back-end turns the resulting -graphs into code suitable for the target environment, e.g. C source code +graphs into code suitable for the target environment, e.g.\ C source code ready to be compiled. @@ -206,15 +206,17 @@ collector's innards. It can inspect all the graphs to discover the \texttt{struct} types in use by the program, and assign a unique type id to each of them. These type ids are collected in internal tables that -describe the layout of the structures, e.g. their sizes and the location +describe the layout of the structures, e.g.\ their sizes and the location of the pointer fields. -We have implemented other transformations as well, e.g. performing -various optimizations, or turning the whole code into a -continuation-passing style (CPS) [XXX I'm not sure our transformation -can be classified as classical CPS, although there are known similar techniques but the terminology is quite confused] that allows us to use coroutines -without giving up the ability to generate fully ANSI C code. (This will -be the subject of another paper.) [XXX mention exception transformer too] +We have implemented other transformations as well, e.g.\ performing +various optimizations, or turning the whole code into a style that +allows us to use coroutines (still in ANSI C: it is a variant of +continuation-passing that will be the subject of another paper.) +Another example is the exception transformer, which transforms graphs +that still contain implicit exception handling into a form suitable for +C (currently based on a global flag to signal the presence of an +exception, set and checked around selected function calls). Finally, currently under development is a variant of the very first transformation step, for use when targeting higher-level, @@ -311,7 +313,7 @@ operations at RPython level is, comparatively speaking, quite large: all list and dictionary operations, instance and class attribute accesses, many string processing methods, a good subset of all Python -built-in functions... Compared to other approaches [e.g. Squeak], we +built-in functions... Compared to other approaches [e.g.\ Squeak], we do not try to minimize the number of primitives -- at least not at the source level. It is fine to have many primitives at any high enough level, because they can all be implemented at the next lower level in @@ -344,7 +346,7 @@ The RPython level is a subset of Python, so the types mostly follow Python types, and the instances of these types are instances in the -normal Python sense; e.g. whereas Python has only got a single type +normal Python sense; e.g.\ whereas Python has only got a single type \texttt{list}, RPython has a parametric type \texttt{list(T)} for every RPython type \texttt{T}, but instances of \texttt{list(T)} are just those Python lists whose items are all instances of \texttt{T}. @@ -611,7 +613,7 @@ inter-procedural call graph. Indeed, we flow types forward from the beginning of the entry point function into each basic block, operation after operation, and follow all calls recursively. During this process, -each variable along the way gets a type. In various cases, e.g. when we +each variable along the way gets a type. In various cases, e.g.\ when we close a loop, the previously assigned types can be found to be too restrictive. In this case, we generalise them to allow for a larger set of possible run-time values, and schedule the block where they appear @@ -719,7 +721,7 @@ It is outside the scope of the present paper to describe the type inference engine and the rules more formally. The difficult points -involve mutable containers -- e.g. initially empty list that are filled +involve mutable containers -- e.g.\ initially empty list that are filled somewhere else -- and the discovery of instance attributes -- in Python, classes do not declare upfront a fixed set of attributes for their instances, let alone their types. Both these examples require @@ -744,7 +746,7 @@ The worst case behaviors that can appear in the model described above involve the lattice of Pbcs, involving variables that could contain -e.g. one function object among many. An example of such behavior is +e.g.\ one function object among many. An example of such behavior is code manipulating a table of function objects: when an item is read out of the table, its type is a large Pbc set: $Pbc(\{f1, f2, f3, \ldots\})$. But in this example, the whole set is available at once, From arigo at codespeak.net Wed May 31 12:12:05 2006 From: arigo at codespeak.net (arigo at codespeak.net) Date: Wed, 31 May 2006 12:12:05 +0200 (CEST) Subject: [pypy-svn] r27960 - pypy/extradoc/talk/dls2006/image Message-ID: <20060531101205.5040610060@code0.codespeak.net> Author: arigo Date: Wed May 31 12:11:59 2006 New Revision: 27960 Modified: pypy/extradoc/talk/dls2006/image/lattice1.pdf pypy/extradoc/talk/dls2006/image/lattice2.pdf Log: The better PDFs produced by rst2pdf. Modified: pypy/extradoc/talk/dls2006/image/lattice1.pdf ============================================================================== Binary files. No diff available. Modified: pypy/extradoc/talk/dls2006/image/lattice2.pdf ============================================================================== Binary files. No diff available. From arigo at codespeak.net Wed May 31 12:17:37 2006 From: arigo at codespeak.net (arigo at codespeak.net) Date: Wed, 31 May 2006 12:17:37 +0200 (CEST) Subject: [pypy-svn] r27961 - pypy/extradoc/talk/dls2006 Message-ID: <20060531101737.865C810036@code0.codespeak.net> Author: arigo Date: Wed May 31 12:17:20 2006 New Revision: 27961 Modified: pypy/extradoc/talk/dls2006/paper.tex Log: Another XXX. Modified: pypy/extradoc/talk/dls2006/paper.tex ============================================================================== --- pypy/extradoc/talk/dls2006/paper.tex (original) +++ pypy/extradoc/talk/dls2006/paper.tex Wed May 31 12:17:20 2006 @@ -413,9 +413,11 @@ We mitigate the potential efficiency problem by wise choices and compromises for the domain used; the foremost example of this is that -our RPython type inference performs almost no automatic specialization -of functions XXX class annotation vs concrete runtime class setsXXX. -We achieved enough precision for our purpose, though. +our RPython type inference performs almost no polymorphic specialization +of functions. Another example is that unlike some schemes which follow +exact sets of concrete run-time classes, we only propagate a single +superclass per variable: the most precise common parent class. This +gives enough precision for our code generation purposes. In the sequel, we give a more precise description of this process and justify our claim that good performance and enough precision can be From arigo at codespeak.net Wed May 31 12:18:11 2006 From: arigo at codespeak.net (arigo at codespeak.net) Date: Wed, 31 May 2006 12:18:11 +0200 (CEST) Subject: [pypy-svn] r27962 - pypy/extradoc/talk/dls2006 Message-ID: <20060531101811.4327C1005A@code0.codespeak.net> Author: arigo Date: Wed May 31 12:18:04 2006 New Revision: 27962 Modified: pypy/extradoc/talk/dls2006/paper.tex Log: i.e. => i.e.\ Modified: pypy/extradoc/talk/dls2006/paper.tex ============================================================================== --- pypy/extradoc/talk/dls2006/paper.tex (original) +++ pypy/extradoc/talk/dls2006/paper.tex Wed May 31 12:18:04 2006 @@ -13,7 +13,7 @@ The PyPy project seeks to prove both on a research and a practical level the feasibility of writing a virtual machine (VM) for a dynamic language in a dynamic language -- in this case, Python. -The aim is to translate (i.e. compile) the VM to arbitrary target +The aim is to translate (i.e.\ compile) the VM to arbitrary target environments, ranging in level from C/Posix to Smalltalk/Squeak via Java and CLI/.NET, while still being of reasonable efficiency within these environments. @@ -161,7 +161,7 @@ subset of Python's built-in types, with some more precision to describe e.g.\ the items stored in container types. Occasionally, a single input function can produce several - specialized versions, i.e. several similar but differently typed + specialized versions, i.e.\ several similar but differently typed graphs. This type inference process is described in more details in section \ref{typeinference}. \end{enumerate} @@ -461,7 +461,7 @@ [figure 3: insert a nice pygame screenshot] \end{verbatim} -The actual transformation from function objects -- i.e. bytecode -- to +The actual transformation from function objects -- i.e.\ bytecode -- to flow graph is performed by the Flow Object Space, a short but generic plug-in component for the Python interpreter of PyPy. The architecture of our Python interpreter is shown in figure \ref{interpobjspace}. @@ -477,7 +477,7 @@ \end{tabular} \end{figure} -Note that the left column, i.e. the bytecode interpreter and the +Note that the left column, i.e.\ the bytecode interpreter and the Standard Object Space, form the full Python interpreter of PyPy. It is an RPython program, and the whole purpose of the translation process is to accept this as \textit{input}, and translate it to an efficient form. Its @@ -602,7 +602,7 @@ the addition and the type of the result depends on the type of the input arguments. Merely knowing that a variable will be used in an addition does not give much information per se. For this reason, our annotator -works by flowing types forward, operation after operation, i.e. by +works by flowing types forward, operation after operation, i.e.\ by performing abstract interpretation of the flow graphs. In a sense, it is a more naive approach than the one taken by type systems specifically designed to enable more advanced inference algorithms. For example, @@ -1038,7 +1038,7 @@ coroutines. To achieve high performance for dynamic languages such as Python, the -proven approach is to use dynamic compilation techniques, i.e. to write +proven approach is to use dynamic compilation techniques, i.e.\ to write JITs. With direct techniques, this is however a major endeavour, and increases the efforts to further evolve the language. From mwh at codespeak.net Wed May 31 12:18:35 2006 From: mwh at codespeak.net (mwh at codespeak.net) Date: Wed, 31 May 2006 12:18:35 +0200 (CEST) Subject: [pypy-svn] r27963 - pypy/extradoc/talk/dls2006 Message-ID: <20060531101835.79CB810063@code0.codespeak.net> Author: mwh Date: Wed May 31 12:18:26 2006 New Revision: 27963 Modified: pypy/extradoc/talk/dls2006/paper.tex Log: use lattice{1,2}.pdf. about zero thought went in to the amount of scaling to use and the captions; tweaking may be desirable. Modified: pypy/extradoc/talk/dls2006/paper.tex ============================================================================== --- pypy/extradoc/talk/dls2006/paper.tex (original) +++ pypy/extradoc/talk/dls2006/paper.tex Wed May 31 12:18:26 2006 @@ -669,22 +669,25 @@ \texttt{None}; resp. an instance or \texttt{None}. \end{itemize} % -Figures 6 and 7 shows how these types are ordered to form a lattice. We -mostly use its structure of [join-semilattice] only. +Figures \ref{latticeoverall} and \ref{latticedetail} show how these +types are ordered to form a lattice. We mostly use its structure of +[join-semilattice] only. -\begin{verbatim} -.. graphviz:: image/lattice1.dot - -:Figure 6: the lattice of annotations. -\end{verbatim} - -\begin{verbatim} -.. graphviz:: image/lattice2.dot +\begin{figure*} +\centering +\includegraphics[scale=0.75]{image/lattice1.pdf} +\caption{The overall lattice} +\label{latticeoverall} +\end{figure*} -:Figure 7: The part about instances and nullable instances, assuming a - simple class hierarchy with only two direct subclasses of - \texttt{object}. -\end{verbatim} +\begin{figure*} +\centering +\includegraphics[scale=0.75]{image/lattice2.pdf} +\caption{The part about instances and nullable instances, assuming a + simple class hierarchy with only two direct subclasses of + \texttt{object}.} +\label{latticedetail} +\end{figure*} All list terms for all variables are unordered. The Pbcs form a From mwh at codespeak.net Wed May 31 12:34:01 2006 From: mwh at codespeak.net (mwh at codespeak.net) Date: Wed, 31 May 2006 12:34:01 +0200 (CEST) Subject: [pypy-svn] r27964 - in pypy/extradoc/talk/dls2006: . image Message-ID: <20060531103401.77BCF1005A@code0.codespeak.net> Author: mwh Date: Wed May 31 12:33:53 2006 New Revision: 27964 Added: pypy/extradoc/talk/dls2006/image/flowlattice.graffle pypy/extradoc/talk/dls2006/image/flowlattice.pdf (contents, props changed) Modified: pypy/extradoc/talk/dls2006/paper.tex Log: a very quick pdf of "figure 5" done in omnigraffle. it might be better to do it in dot instead, for consistency with the other lattices -- or remove it entirely, i'm not sure it's worth the space it takes up. Added: pypy/extradoc/talk/dls2006/image/flowlattice.graffle ============================================================================== --- (empty file) +++ pypy/extradoc/talk/dls2006/image/flowlattice.graffle Wed May 31 12:33:53 2006 @@ -0,0 +1,534 @@ + + + + + CanvasColor + + w + 1 + + ColumnAlign + 1 + ColumnSpacing + 36 + CreationDate + 2006-05-31 11:20:18 +0100 + Creator + Michael Hudson + GraphDocumentVersion + 4 + GraphicsList + + + Class + LineGraphic + Head + + ID + 6 + + ID + 11 + Points + + {333.5, 122} + {389, 122} + + Style + + stroke + + HeadArrow + 0 + Pattern + 1 + TailArrow + 0 + + + Tail + + ID + 5 + + + + Class + LineGraphic + Head + + ID + 6 + + ID + 10 + Points + + {306.097, 64} + {416.403, 108} + + Style + + stroke + + HeadArrow + 0 + TailArrow + 0 + + + Tail + + ID + 3 + + + + Class + LineGraphic + Head + + ID + 5 + + ID + 9 + Points + + {271, 64} + {271, 108} + + Style + + stroke + + HeadArrow + 0 + TailArrow + 0 + + + Tail + + ID + 3 + + + + Class + LineGraphic + Head + + ID + 3 + + ID + 8 + Points + + {125.597, 108} + {235.903, 64} + + Style + + stroke + + HeadArrow + 0 + TailArrow + 0 + + + Tail + + ID + 4 + + + + Class + LineGraphic + Head + + ID + 5 + + ID + 7 + Points + + {153, 122} + {208.5, 122} + + Style + + stroke + + HeadArrow + 0 + LineType + 1 + Pattern + 1 + TailArrow + 0 + + + Tail + + ID + 4 + + + + Bounds + {{389, 108}, {125, 28}} + Class + ShapedGraphic + ID + 6 + Shape + RoundRect + Style + + shadow + + Draws + NO + + + Text + + Text + {\rtf1\mac\ansicpg10000\cocoartf824\cocoasubrtf380 +{\fonttbl\f0\fswiss\fcharset77 Helvetica;} +{\colortbl;\red255\green255\blue255;} +\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\qc\pardirnatural + +\f0\fs24 \cf0 Constant([1,2,3])} + + + + Bounds + {{208.5, 108}, {125, 28}} + Class + ShapedGraphic + ID + 5 + Shape + RoundRect + Style + + shadow + + Draws + NO + + + Text + + Text + {\rtf1\mac\ansicpg10000\cocoartf824\cocoasubrtf380 +{\fonttbl\f0\fswiss\fcharset77 Helvetica;} +{\colortbl;\red255\green255\blue255;} +\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\qc\pardirnatural + +\f0\fs24 \cf0 Constant(n)} + + + + Bounds + {{28, 108}, {125, 28}} + Class + ShapedGraphic + ID + 4 + Shape + RoundRect + Style + + shadow + + Draws + NO + + + Text + + Text + {\rtf1\mac\ansicpg10000\cocoartf824\cocoasubrtf380 +{\fonttbl\f0\fswiss\fcharset77 Helvetica;} +{\colortbl;\red255\green255\blue255;} +\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\qc\pardirnatural + +\f0\fs24 \cf0 Constant(1)} + + + + Bounds + {{208.5, 36}, {125, 28}} + Class + ShapedGraphic + ID + 3 + Shape + RoundRect + Style + + shadow + + Draws + NO + + + Text + + Text + {\rtf1\mac\ansicpg10000\cocoartf824\cocoasubrtf380 +{\fonttbl\f0\fswiss\fcharset77 Helvetica;} +{\colortbl;\red255\green255\blue255;} +\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\qc\pardirnatural + +\f0\fs24 \cf0 Variable} + + + + GridInfo + + GuidesLocked + NO + GuidesVisible + YES + HPages + 1 + ImageCounter + 1 + IsPalette + NO + Layers + + + Lock + NO + Name + Layer 1 + Print + YES + View + YES + + + LayoutInfo + + LinksVisible + NO + MagnetsVisible + NO + ModificationDate + 2006-05-31 11:28:05 +0100 + Modifier + Michael Hudson + Orientation + 2 + PageBreaks + YES + PageSetup + + BAt0eXBlZHN0cmVhbYED6IQBQISEhAtOU1ByaW50SW5mbwGEhAhOU09iamVjdACFkoSE + hBNOU011dGFibGVEaWN0aW9uYXJ5AISEDE5TRGljdGlvbmFyeQCUhAFpFJKEhIQITlNT + dHJpbmcBlIQBKxBOU0pvYkRpc3Bvc2l0aW9uhpKEmZkPTlNQcmludFNwb29sSm9ihpKE + mZkLTlNQYXBlclNpemWGkoSEhAdOU1ZhbHVlAJSEASqEhAx7X05TU2l6ZT1mZn2cgQJk + gQMYhpKEmZkUTlNWZXJ0aWNhbFBhZ2luYXRpb26GkoSEhAhOU051bWJlcgCdm4SXlwCG + koSZmQ5OU1BNUGFnZUZvcm1hdIaShISEDU5TTXV0YWJsZURhdGEAhIQGTlNEYXRhAJSX + gR2thAdbNzU5N2NdPD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0iVVRGLTgiPz4K + PCFET0NUWVBFIHBsaXN0IFBVQkxJQyAiLS8vQXBwbGUgQ29tcHV0ZXIvL0RURCBQTElT + VCAxLjAvL0VOIiAiaHR0cDovL3d3dy5hcHBsZS5jb20vRFREcy9Qcm9wZXJ0eUxpc3Qt + MS4wLmR0ZCI+CjxwbGlzdCB2ZXJzaW9uPSIxLjAiPgo8ZGljdD4KCTxrZXk+Y29tLmFw + cGxlLnByaW50LlBhZ2VGb3JtYXQuUE1Ib3Jpem9udGFsUmVzPC9rZXk+Cgk8ZGljdD4K + CQk8a2V5PmNvbS5hcHBsZS5wcmludC50aWNrZXQuY3JlYXRvcjwva2V5PgoJCTxzdHJp + bmc+Y29tLmFwcGxlLnByaW50aW5nbWFuYWdlcjwvc3RyaW5nPgoJCTxrZXk+Y29tLmFw + cGxlLnByaW50LnRpY2tldC5pdGVtQXJyYXk8L2tleT4KCQk8YXJyYXk+CgkJCTxkaWN0 + PgoJCQkJPGtleT5jb20uYXBwbGUucHJpbnQuUGFnZUZvcm1hdC5QTUhvcml6b250YWxS + ZXM8L2tleT4KCQkJCTxyZWFsPjcyPC9yZWFsPgoJCQkJPGtleT5jb20uYXBwbGUucHJp + bnQudGlja2V0LmNsaWVudDwva2V5PgoJCQkJPHN0cmluZz5jb20uYXBwbGUucHJpbnRp + bmdtYW5hZ2VyPC9zdHJpbmc+CgkJCQk8a2V5PmNvbS5hcHBsZS5wcmludC50aWNrZXQu + bW9kRGF0ZTwva2V5PgoJCQkJPGRhdGU+MjAwMy0wMS0yNFQxNjoyODo1NFo8L2RhdGU+ + CgkJCQk8a2V5PmNvbS5hcHBsZS5wcmludC50aWNrZXQuc3RhdGVGbGFnPC9rZXk+CgkJ + CQk8aW50ZWdlcj4wPC9pbnRlZ2VyPgoJCQk8L2RpY3Q+CgkJPC9hcnJheT4KCTwvZGlj + dD4KCTxrZXk+Y29tLmFwcGxlLnByaW50LlBhZ2VGb3JtYXQuUE1PcmllbnRhdGlvbjwv + a2V5PgoJPGRpY3Q+CgkJPGtleT5jb20uYXBwbGUucHJpbnQudGlja2V0LmNyZWF0b3I8 + L2tleT4KCQk8c3RyaW5nPmNvbS5hcHBsZS5wcmludGluZ21hbmFnZXI8L3N0cmluZz4K + CQk8a2V5PmNvbS5hcHBsZS5wcmludC50aWNrZXQuaXRlbUFycmF5PC9rZXk+CgkJPGFy + cmF5PgoJCQk8ZGljdD4KCQkJCTxrZXk+Y29tLmFwcGxlLnByaW50LlBhZ2VGb3JtYXQu + UE1PcmllbnRhdGlvbjwva2V5PgoJCQkJPGludGVnZXI+MTwvaW50ZWdlcj4KCQkJCTxr + ZXk+Y29tLmFwcGxlLnByaW50LnRpY2tldC5jbGllbnQ8L2tleT4KCQkJCTxzdHJpbmc+ + Y29tLmFwcGxlLnByaW50aW5nbWFuYWdlcjwvc3RyaW5nPgoJCQkJPGtleT5jb20uYXBw + bGUucHJpbnQudGlja2V0Lm1vZERhdGU8L2tleT4KCQkJCTxkYXRlPjIwMDMtMDEtMjRU + MTY6Mjg6NTRaPC9kYXRlPgoJCQkJPGtleT5jb20uYXBwbGUucHJpbnQudGlja2V0LnN0 + YXRlRmxhZzwva2V5PgoJCQkJPGludGVnZXI+MDwvaW50ZWdlcj4KCQkJPC9kaWN0PgoJ + CTwvYXJyYXk+Cgk8L2RpY3Q+Cgk8a2V5PmNvbS5hcHBsZS5wcmludC5QYWdlRm9ybWF0 + LlBNU2NhbGluZzwva2V5PgoJPGRpY3Q+CgkJPGtleT5jb20uYXBwbGUucHJpbnQudGlj + a2V0LmNyZWF0b3I8L2tleT4KCQk8c3RyaW5nPmNvbS5hcHBsZS5wcmludGluZ21hbmFn + ZXI8L3N0cmluZz4KCQk8a2V5PmNvbS5hcHBsZS5wcmludC50aWNrZXQuaXRlbUFycmF5 + PC9rZXk+CgkJPGFycmF5PgoJCQk8ZGljdD4KCQkJCTxrZXk+Y29tLmFwcGxlLnByaW50 + LlBhZ2VGb3JtYXQuUE1TY2FsaW5nPC9rZXk+CgkJCQk8cmVhbD4xPC9yZWFsPgoJCQkJ + PGtleT5jb20uYXBwbGUucHJpbnQudGlja2V0LmNsaWVudDwva2V5PgoJCQkJPHN0cmlu + Zz5jb20uYXBwbGUucHJpbnRpbmdtYW5hZ2VyPC9zdHJpbmc+CgkJCQk8a2V5PmNvbS5h + cHBsZS5wcmludC50aWNrZXQubW9kRGF0ZTwva2V5PgoJCQkJPGRhdGU+MjAwMy0wMS0y + NFQxNjoyODo1NFo8L2RhdGU+CgkJCQk8a2V5PmNvbS5hcHBsZS5wcmludC50aWNrZXQu + c3RhdGVGbGFnPC9rZXk+CgkJCQk8aW50ZWdlcj4wPC9pbnRlZ2VyPgoJCQk8L2RpY3Q+ + CgkJPC9hcnJheT4KCTwvZGljdD4KCTxrZXk+Y29tLmFwcGxlLnByaW50LlBhZ2VGb3Jt + YXQuUE1WZXJ0aWNhbFJlczwva2V5PgoJPGRpY3Q+CgkJPGtleT5jb20uYXBwbGUucHJp + bnQudGlja2V0LmNyZWF0b3I8L2tleT4KCQk8c3RyaW5nPmNvbS5hcHBsZS5wcmludGlu + Z21hbmFnZXI8L3N0cmluZz4KCQk8a2V5PmNvbS5hcHBsZS5wcmludC50aWNrZXQuaXRl + bUFycmF5PC9rZXk+CgkJPGFycmF5PgoJCQk8ZGljdD4KCQkJCTxrZXk+Y29tLmFwcGxl + LnByaW50LlBhZ2VGb3JtYXQuUE1WZXJ0aWNhbFJlczwva2V5PgoJCQkJPHJlYWw+NzI8 + L3JlYWw+CgkJCQk8a2V5PmNvbS5hcHBsZS5wcmludC50aWNrZXQuY2xpZW50PC9rZXk+ + CgkJCQk8c3RyaW5nPmNvbS5hcHBsZS5wcmludGluZ21hbmFnZXI8L3N0cmluZz4KCQkJ + CTxrZXk+Y29tLmFwcGxlLnByaW50LnRpY2tldC5tb2REYXRlPC9rZXk+CgkJCQk8ZGF0 + ZT4yMDAzLTAxLTI0VDE2OjI4OjU0WjwvZGF0ZT4KCQkJCTxrZXk+Y29tLmFwcGxlLnBy + aW50LnRpY2tldC5zdGF0ZUZsYWc8L2tleT4KCQkJCTxpbnRlZ2VyPjA8L2ludGVnZXI+ + CgkJCTwvZGljdD4KCQk8L2FycmF5PgoJPC9kaWN0PgoJPGtleT5jb20uYXBwbGUucHJp + bnQuUGFnZUZvcm1hdC5QTVZlcnRpY2FsU2NhbGluZzwva2V5PgoJPGRpY3Q+CgkJPGtl + eT5jb20uYXBwbGUucHJpbnQudGlja2V0LmNyZWF0b3I8L2tleT4KCQk8c3RyaW5nPmNv + bS5hcHBsZS5wcmludGluZ21hbmFnZXI8L3N0cmluZz4KCQk8a2V5PmNvbS5hcHBsZS5w + cmludC50aWNrZXQuaXRlbUFycmF5PC9rZXk+CgkJPGFycmF5PgoJCQk8ZGljdD4KCQkJ + CTxrZXk+Y29tLmFwcGxlLnByaW50LlBhZ2VGb3JtYXQuUE1WZXJ0aWNhbFNjYWxpbmc8 + L2tleT4KCQkJCTxyZWFsPjE8L3JlYWw+CgkJCQk8a2V5PmNvbS5hcHBsZS5wcmludC50 + aWNrZXQuY2xpZW50PC9rZXk+CgkJCQk8c3RyaW5nPmNvbS5hcHBsZS5wcmludGluZ21h + bmFnZXI8L3N0cmluZz4KCQkJCTxrZXk+Y29tLmFwcGxlLnByaW50LnRpY2tldC5tb2RE + YXRlPC9rZXk+CgkJCQk8ZGF0ZT4yMDAzLTAxLTI0VDE2OjI4OjU0WjwvZGF0ZT4KCQkJ + CTxrZXk+Y29tLmFwcGxlLnByaW50LnRpY2tldC5zdGF0ZUZsYWc8L2tleT4KCQkJCTxp + bnRlZ2VyPjA8L2ludGVnZXI+CgkJCTwvZGljdD4KCQk8L2FycmF5PgoJPC9kaWN0PgoJ + PGtleT5jb20uYXBwbGUucHJpbnQuc3ViVGlja2V0LnBhcGVyX2luZm9fdGlja2V0PC9r + ZXk+Cgk8ZGljdD4KCQk8a2V5PmNvbS5hcHBsZS5wcmludC5QYWdlRm9ybWF0LlBNQWRq + dXN0ZWRQYWdlUmVjdDwva2V5PgoJCTxkaWN0PgoJCQk8a2V5PmNvbS5hcHBsZS5wcmlu + dC50aWNrZXQuY3JlYXRvcjwva2V5PgoJCQk8c3RyaW5nPmNvbS5hcHBsZS5wcmludGlu + Z21hbmFnZXI8L3N0cmluZz4KCQkJPGtleT5jb20uYXBwbGUucHJpbnQudGlja2V0Lml0 + ZW1BcnJheTwva2V5PgoJCQk8YXJyYXk+CgkJCQk8ZGljdD4KCQkJCQk8a2V5PmNvbS5h + cHBsZS5wcmludC5QYWdlRm9ybWF0LlBNQWRqdXN0ZWRQYWdlUmVjdDwva2V5PgoJCQkJ + CTxhcnJheT4KCQkJCQkJPHJlYWw+MC4wPC9yZWFsPgoJCQkJCQk8cmVhbD4wLjA8L3Jl + YWw+CgkJCQkJCTxyZWFsPjczNDwvcmVhbD4KCQkJCQkJPHJlYWw+NTc2PC9yZWFsPgoJ + CQkJCTwvYXJyYXk+CgkJCQkJPGtleT5jb20uYXBwbGUucHJpbnQudGlja2V0LmNsaWVu + dDwva2V5PgoJCQkJCTxzdHJpbmc+Y29tLmFwcGxlLnByaW50aW5nbWFuYWdlcjwvc3Ry + aW5nPgoJCQkJCTxrZXk+Y29tLmFwcGxlLnByaW50LnRpY2tldC5tb2REYXRlPC9rZXk+ + CgkJCQkJPGRhdGU+MjAwNi0wNS0zMVQxMDoyMDoxOFo8L2RhdGU+CgkJCQkJPGtleT5j + b20uYXBwbGUucHJpbnQudGlja2V0LnN0YXRlRmxhZzwva2V5PgoJCQkJCTxpbnRlZ2Vy + PjA8L2ludGVnZXI+CgkJCQk8L2RpY3Q+CgkJCTwvYXJyYXk+CgkJPC9kaWN0PgoJCTxr + ZXk+Y29tLmFwcGxlLnByaW50LlBhZ2VGb3JtYXQuUE1BZGp1c3RlZFBhcGVyUmVjdDwv + a2V5PgoJCTxkaWN0PgoJCQk8a2V5PmNvbS5hcHBsZS5wcmludC50aWNrZXQuY3JlYXRv + cjwva2V5PgoJCQk8c3RyaW5nPmNvbS5hcHBsZS5wcmludGluZ21hbmFnZXI8L3N0cmlu + Zz4KCQkJPGtleT5jb20uYXBwbGUucHJpbnQudGlja2V0Lml0ZW1BcnJheTwva2V5PgoJ + CQk8YXJyYXk+CgkJCQk8ZGljdD4KCQkJCQk8a2V5PmNvbS5hcHBsZS5wcmludC5QYWdl + Rm9ybWF0LlBNQWRqdXN0ZWRQYXBlclJlY3Q8L2tleT4KCQkJCQk8YXJyYXk+CgkJCQkJ + CTxyZWFsPi0xODwvcmVhbD4KCQkJCQkJPHJlYWw+LTE4PC9yZWFsPgoJCQkJCQk8cmVh + bD43NzQ8L3JlYWw+CgkJCQkJCTxyZWFsPjU5NDwvcmVhbD4KCQkJCQk8L2FycmF5PgoJ + CQkJCTxrZXk+Y29tLmFwcGxlLnByaW50LnRpY2tldC5jbGllbnQ8L2tleT4KCQkJCQk8 + c3RyaW5nPmNvbS5hcHBsZS5wcmludGluZ21hbmFnZXI8L3N0cmluZz4KCQkJCQk8a2V5 + PmNvbS5hcHBsZS5wcmludC50aWNrZXQubW9kRGF0ZTwva2V5PgoJCQkJCTxkYXRlPjIw + MDYtMDUtMzFUMTA6MjA6MThaPC9kYXRlPgoJCQkJCTxrZXk+Y29tLmFwcGxlLnByaW50 + LnRpY2tldC5zdGF0ZUZsYWc8L2tleT4KCQkJCQk8aW50ZWdlcj4wPC9pbnRlZ2VyPgoJ + CQkJPC9kaWN0PgoJCQk8L2FycmF5PgoJCTwvZGljdD4KCQk8a2V5PmNvbS5hcHBsZS5w + cmludC5QYXBlckluZm8uUE1QYXBlck5hbWU8L2tleT4KCQk8ZGljdD4KCQkJPGtleT5j + b20uYXBwbGUucHJpbnQudGlja2V0LmNyZWF0b3I8L2tleT4KCQkJPHN0cmluZz5jb20u + YXBwbGUucHJpbnQucG0uUG9zdFNjcmlwdDwvc3RyaW5nPgoJCQk8a2V5PmNvbS5hcHBs + ZS5wcmludC50aWNrZXQuaXRlbUFycmF5PC9rZXk+CgkJCTxhcnJheT4KCQkJCTxkaWN0 + PgoJCQkJCTxrZXk+Y29tLmFwcGxlLnByaW50LlBhcGVySW5mby5QTVBhcGVyTmFtZTwv + a2V5PgoJCQkJCTxzdHJpbmc+bmEtbGV0dGVyPC9zdHJpbmc+CgkJCQkJPGtleT5jb20u + YXBwbGUucHJpbnQudGlja2V0LmNsaWVudDwva2V5PgoJCQkJCTxzdHJpbmc+Y29tLmFw + cGxlLnByaW50LnBtLlBvc3RTY3JpcHQ8L3N0cmluZz4KCQkJCQk8a2V5PmNvbS5hcHBs + ZS5wcmludC50aWNrZXQubW9kRGF0ZTwva2V5PgoJCQkJCTxkYXRlPjIwMDAtMDctMjhU + MjI6NTc6MDRaPC9kYXRlPgoJCQkJCTxrZXk+Y29tLmFwcGxlLnByaW50LnRpY2tldC5z + dGF0ZUZsYWc8L2tleT4KCQkJCQk8aW50ZWdlcj4xPC9pbnRlZ2VyPgoJCQkJPC9kaWN0 + PgoJCQk8L2FycmF5PgoJCTwvZGljdD4KCQk8a2V5PmNvbS5hcHBsZS5wcmludC5QYXBl + ckluZm8uUE1VbmFkanVzdGVkUGFnZVJlY3Q8L2tleT4KCQk8ZGljdD4KCQkJPGtleT5j + b20uYXBwbGUucHJpbnQudGlja2V0LmNyZWF0b3I8L2tleT4KCQkJPHN0cmluZz5jb20u + YXBwbGUucHJpbnQucG0uUG9zdFNjcmlwdDwvc3RyaW5nPgoJCQk8a2V5PmNvbS5hcHBs + ZS5wcmludC50aWNrZXQuaXRlbUFycmF5PC9rZXk+CgkJCTxhcnJheT4KCQkJCTxkaWN0 + PgoJCQkJCTxrZXk+Y29tLmFwcGxlLnByaW50LlBhcGVySW5mby5QTVVuYWRqdXN0ZWRQ + YWdlUmVjdDwva2V5PgoJCQkJCTxhcnJheT4KCQkJCQkJPHJlYWw+MC4wPC9yZWFsPgoJ + CQkJCQk8cmVhbD4wLjA8L3JlYWw+CgkJCQkJCTxyZWFsPjczNDwvcmVhbD4KCQkJCQkJ + PHJlYWw+NTc2PC9yZWFsPgoJCQkJCTwvYXJyYXk+CgkJCQkJPGtleT5jb20uYXBwbGUu + cHJpbnQudGlja2V0LmNsaWVudDwva2V5PgoJCQkJCTxzdHJpbmc+Y29tLmFwcGxlLnBy + aW50aW5nbWFuYWdlcjwvc3RyaW5nPgoJCQkJCTxrZXk+Y29tLmFwcGxlLnByaW50LnRp + Y2tldC5tb2REYXRlPC9rZXk+CgkJCQkJPGRhdGU+MjAwMy0wMS0yNFQxNjoyODo1NFo8 + L2RhdGU+CgkJCQkJPGtleT5jb20uYXBwbGUucHJpbnQudGlja2V0LnN0YXRlRmxhZzwv + a2V5PgoJCQkJCTxpbnRlZ2VyPjA8L2ludGVnZXI+CgkJCQk8L2RpY3Q+CgkJCTwvYXJy + YXk+CgkJPC9kaWN0PgoJCTxrZXk+Y29tLmFwcGxlLnByaW50LlBhcGVySW5mby5QTVVu + YWRqdXN0ZWRQYXBlclJlY3Q8L2tleT4KCQk8ZGljdD4KCQkJPGtleT5jb20uYXBwbGUu + cHJpbnQudGlja2V0LmNyZWF0b3I8L2tleT4KCQkJPHN0cmluZz5jb20uYXBwbGUucHJp + bnQucG0uUG9zdFNjcmlwdDwvc3RyaW5nPgoJCQk8a2V5PmNvbS5hcHBsZS5wcmludC50 + aWNrZXQuaXRlbUFycmF5PC9rZXk+CgkJCTxhcnJheT4KCQkJCTxkaWN0PgoJCQkJCTxr + ZXk+Y29tLmFwcGxlLnByaW50LlBhcGVySW5mby5QTVVuYWRqdXN0ZWRQYXBlclJlY3Q8 + L2tleT4KCQkJCQk8YXJyYXk+CgkJCQkJCTxyZWFsPi0xODwvcmVhbD4KCQkJCQkJPHJl + YWw+LTE4PC9yZWFsPgoJCQkJCQk8cmVhbD43NzQ8L3JlYWw+CgkJCQkJCTxyZWFsPjU5 + NDwvcmVhbD4KCQkJCQk8L2FycmF5PgoJCQkJCTxrZXk+Y29tLmFwcGxlLnByaW50LnRp + Y2tldC5jbGllbnQ8L2tleT4KCQkJCQk8c3RyaW5nPmNvbS5hcHBsZS5wcmludGluZ21h + bmFnZXI8L3N0cmluZz4KCQkJCQk8a2V5PmNvbS5hcHBsZS5wcmludC50aWNrZXQubW9k + RGF0ZTwva2V5PgoJCQkJCTxkYXRlPjIwMDMtMDEtMjRUMTY6Mjg6NTRaPC9kYXRlPgoJ + CQkJCTxrZXk+Y29tLmFwcGxlLnByaW50LnRpY2tldC5zdGF0ZUZsYWc8L2tleT4KCQkJ + CQk8aW50ZWdlcj4wPC9pbnRlZ2VyPgoJCQkJPC9kaWN0PgoJCQk8L2FycmF5PgoJCTwv + ZGljdD4KCQk8a2V5PmNvbS5hcHBsZS5wcmludC5QYXBlckluZm8ucHBkLlBNUGFwZXJO + YW1lPC9rZXk+CgkJPGRpY3Q+CgkJCTxrZXk+Y29tLmFwcGxlLnByaW50LnRpY2tldC5j + cmVhdG9yPC9rZXk+CgkJCTxzdHJpbmc+Y29tLmFwcGxlLnByaW50LnBtLlBvc3RTY3Jp + cHQ8L3N0cmluZz4KCQkJPGtleT5jb20uYXBwbGUucHJpbnQudGlja2V0Lml0ZW1BcnJh + eTwva2V5PgoJCQk8YXJyYXk+CgkJCQk8ZGljdD4KCQkJCQk8a2V5PmNvbS5hcHBsZS5w + cmludC5QYXBlckluZm8ucHBkLlBNUGFwZXJOYW1lPC9rZXk+CgkJCQkJPHN0cmluZz5M + ZXR0ZXI8L3N0cmluZz4KCQkJCQk8a2V5PmNvbS5hcHBsZS5wcmludC50aWNrZXQuY2xp + ZW50PC9rZXk+CgkJCQkJPHN0cmluZz5jb20uYXBwbGUucHJpbnQucG0uUG9zdFNjcmlw + dDwvc3RyaW5nPgoJCQkJCTxrZXk+Y29tLmFwcGxlLnByaW50LnRpY2tldC5tb2REYXRl + PC9rZXk+CgkJCQkJPGRhdGU+MjAwMC0wNy0yOFQyMjo1NzowNFo8L2RhdGU+CgkJCQkJ + PGtleT5jb20uYXBwbGUucHJpbnQudGlja2V0LnN0YXRlRmxhZzwva2V5PgoJCQkJCTxp + bnRlZ2VyPjE8L2ludGVnZXI+CgkJCQk8L2RpY3Q+CgkJCTwvYXJyYXk+CgkJPC9kaWN0 + PgoJCTxrZXk+Y29tLmFwcGxlLnByaW50LnRpY2tldC5BUElWZXJzaW9uPC9rZXk+CgkJ + PHN0cmluZz4wMC4yMDwvc3RyaW5nPgoJCTxrZXk+Y29tLmFwcGxlLnByaW50LnRpY2tl + dC5wcml2YXRlTG9jazwva2V5PgoJCTxmYWxzZS8+CgkJPGtleT5jb20uYXBwbGUucHJp + bnQudGlja2V0LnR5cGU8L2tleT4KCQk8c3RyaW5nPmNvbS5hcHBsZS5wcmludC5QYXBl + ckluZm9UaWNrZXQ8L3N0cmluZz4KCTwvZGljdD4KCTxrZXk+Y29tLmFwcGxlLnByaW50 + LnRpY2tldC5BUElWZXJzaW9uPC9rZXk+Cgk8c3RyaW5nPjAwLjIwPC9zdHJpbmc+Cgk8 + a2V5PmNvbS5hcHBsZS5wcmludC50aWNrZXQucHJpdmF0ZUxvY2s8L2tleT4KCTxmYWxz + ZS8+Cgk8a2V5PmNvbS5hcHBsZS5wcmludC50aWNrZXQudHlwZTwva2V5PgoJPHN0cmlu + Zz5jb20uYXBwbGUucHJpbnQuUGFnZUZvcm1hdFRpY2tldDwvc3RyaW5nPgo8L2RpY3Q+ + CjwvcGxpc3Q+CoaShJmZFE5TVmVydGljYWxseUNlbnRlcmVkhpKEoZuilwGGkoSZmQ9O + U1ByaW50QWxsUGFnZXOGkqCShJmZCE5TQ29waWVzhpKokoSZmQtOU1BhcGVyTmFtZYaS + hJmZBkxldHRlcoaShJmZD05TU2NhbGluZ0ZhY3RvcoaShKGbhIQBZqEBhpKEmZkJTlNQ + cmludGVyhpKEhIQJTlNQcmludGVyAJSShJmZA2hwMIaGkoSZmQ1OU1JpZ2h0TWFyZ2lu + hpKEoZuvoQCGkoSZmRVOU0hvcml6b25hbFBhZ2luYXRpb26GkqCShJmZGU5TUHJpbnRS + ZXZlcnNlT3JpZW50YXRpb26GkqCShJmZDk5TQm90dG9tTWFyZ2luhpKEoZuvoQCGkoSZ + mQxOU0xlZnRNYXJnaW6GkoShm6+hAIaShJmZC05TVG9wTWFyZ2luhpKEoZuvoQCGkoSZ + mQpOU0xhc3RQYWdlhpKEoZuil4J/////hpKEmZkLTlNGaXJzdFBhZ2WGkqiShJmZFk5T + SG9yaXpvbnRhbGx5Q2VudGVyZWSGkqiShJmZDU5TT3JpZW50YXRpb26GkqCGhg== + + ReadOnly + NO + RowAlign + 1 + RowSpacing + 36 + SheetTitle + Canvas 1 + SmartAlignmentGuidesActive + YES + SmartDistanceGuidesActive + YES + UseEntirePage + + VPages + 1 + WindowInfo + + CurrentSheet + 0 + Frame + {{444, 58}, {591, 820}} + ShowRuler + + ShowStatusBar + + VisibleRegion + {{0, 0}, {576, 722}} + Zoom + 1 + + + Added: pypy/extradoc/talk/dls2006/image/flowlattice.pdf ============================================================================== Binary file. No diff available. Modified: pypy/extradoc/talk/dls2006/paper.tex ============================================================================== --- pypy/extradoc/talk/dls2006/paper.tex (original) +++ pypy/extradoc/talk/dls2006/paper.tex Wed May 31 12:33:53 2006 @@ -494,19 +494,14 @@ objects are the concrete Python objects of the various built-in types: lists, dictionaries, and so on. By opposition, the Flow Object Space is really an abstract domain. It handles objects that are placeholders. -Its lattice order is shown in figure 5. +Its lattice order is shown in figure \ref{flowlattice}. -\begin{verbatim} -:: - - [figure 5: Variable - - / | \ \ - / | \ \ - / | \ \ - Constant(1) ... Constant(n) ... Constant([1,2,3]) ... Constant() ... - ] -\end{verbatim} +\begin{figure*} +\centering +\includegraphics[scale=0.75]{image/flowlattice.pdf} +\caption{The lattice order of the flow object space} +\label{flowlattice} +\end{figure*} This order is extremely simple, because most actual analysis is delayed to the next phase, the type inference engine. The objects are either From arigo at codespeak.net Wed May 31 12:38:48 2006 From: arigo at codespeak.net (arigo at codespeak.net) Date: Wed, 31 May 2006 12:38:48 +0200 (CEST) Subject: [pypy-svn] r27965 - pypy/extradoc/talk/dls2006 Message-ID: <20060531103848.7331210060@code0.codespeak.net> Author: arigo Date: Wed May 31 12:38:41 2006 New Revision: 27965 Modified: pypy/extradoc/talk/dls2006/paper.tex Log: More XXXes. Modified: pypy/extradoc/talk/dls2006/paper.tex ============================================================================== --- pypy/extradoc/talk/dls2006/paper.tex (original) +++ pypy/extradoc/talk/dls2006/paper.tex Wed May 31 12:38:41 2006 @@ -480,8 +480,9 @@ Note that the left column, i.e.\ the bytecode interpreter and the Standard Object Space, form the full Python interpreter of PyPy. It is an RPython program, and the whole purpose of the translation process is -to accept this as \textit{input}, and translate it to an efficient form. Its -architecture is not relevant to the way it is translated. XXX? +to accept this as \textit{input}, and translate it to an efficient form. +The description of this particular input program is beyond the scope of +the present paper; see [S]. However, the bytecode interpreter plays a double role, at two different levels. The so-called Object Spaces are \textit{domains} in the abstract @@ -535,7 +536,10 @@ some constructs of the bytecode interpreter, which can temporarily wrap internal values and push them onto the regular value stack among the other application-level objects. We need to be able to unwrap -them again later. XXX compile-time computation in the helpers.} +them again later. Moreover, we rely on this feature to perform +compile-time computations, particularly in the generic system code +helpers, which ask for and compute with the concrete types of the +variables they receive.} In the flow graph, branching occurs when the bytecode interpreter tries to inspect the truth value of placeholder objects, as it would in @@ -699,21 +703,34 @@ to $A$; it is a "binding" that gives to each variable a type. The purpose of the annotator is to compute such a binding stepwise. -Let $x$, $y$ and $z$ be Variables. We introduce the rule: - -% XXX format this! +Let $x$, $y$ and $z$ be Variables. We introduce the rules: +% $$ \begin{array}{c} z = \mathrm{add}(x, y), \; b(x) = - Int, \; Bool \leq b(y) \leq Int \\ \hline + Int, \; b(y) = Int \\ \hline b' = b \hbox{\ with\ } (z \rightarrow Int) \end{array} $$ - -which specify that if we see the addition operation applied to +% +$$ +\begin{array}{c} + z = \mathrm{add}(x, y), \; Bool \leq b(x), b(y) \leq + NonNegInt \\ \hline + b' = b \hbox{\ with\ } (z + \rightarrow NonNegInt) +\end{array} +$$ +% +The first rule specifies that if we see the addition operation applied to Variables whose current binding is $Int$, a new binding $b'$ can be produced: it is $b$ except on $z$, where we have $b'(z) = Int$. +The second rule specifies that in a similar case, if both arguments are +known to be non-negative, so is the result. Extra rules control addition +between other combinations of numbers, as well as strings, lists and tuples +(for which addition is concatenation). Similar sets of rules are +introduced for each operation. The type inference engine can be seen as applying this kind of rules repeatedly. It does not apply them in random order, but follows a From mwh at codespeak.net Wed May 31 12:52:13 2006 From: mwh at codespeak.net (mwh at codespeak.net) Date: Wed, 31 May 2006 12:52:13 +0200 (CEST) Subject: [pypy-svn] r27966 - pypy/extradoc/talk/dls2006 Message-ID: <20060531105213.EE5601005A@code0.codespeak.net> Author: mwh Date: Wed May 31 12:52:10 2006 New Revision: 27966 Modified: pypy/extradoc/talk/dls2006/paper.tex Log: add two authors Modified: pypy/extradoc/talk/dls2006/paper.tex ============================================================================== --- pypy/extradoc/talk/dls2006/paper.tex (original) +++ pypy/extradoc/talk/dls2006/paper.tex Wed May 31 12:52:10 2006 @@ -7,6 +7,23 @@ % title ideas: Implementing Virtual Machines in Dynamic Languages? +\numberofauthors{2} +\author{ +\alignauthor Armin Rigo\\ + \affaddr{Heinrich-Heine-Universit?t D?sseldorf}\\ + \affaddr{Institut f?r Informatik}\\ + \affaddr{Universit?tsstra?e 1}\\ + \affaddr{D-40225 D?sseldorf}\\ + \affaddr{Deutschland}\\ + \email{arigo at tunes.org} +\alignauthor Samuele Pedroni\\ + \affaddr{AB Strakt}\\ + \affaddr{Norra ?gatan 10A}\\ + \affaddr{416 64 G?teborg}\\ + \affaddr{Sweden}\\ + \email{pedronis at strakt.com} +} +\date{31 May 2006} \maketitle \begin{abstract} From arigo at codespeak.net Wed May 31 12:53:19 2006 From: arigo at codespeak.net (arigo at codespeak.net) Date: Wed, 31 May 2006 12:53:19 +0200 (CEST) Subject: [pypy-svn] r27967 - pypy/extradoc/talk/dls2006/image Message-ID: <20060531105319.B570C10036@code0.codespeak.net> Author: arigo Date: Wed May 31 12:53:15 2006 New Revision: 27967 Added: pypy/extradoc/talk/dls2006/image/flowlattice.dot Modified: pypy/extradoc/talk/dls2006/image/flowlattice.pdf pypy/extradoc/talk/dls2006/image/lattice1.pdf pypy/extradoc/talk/dls2006/image/lattice2.pdf Log: A dot version of flowlattice. Bounding box too small :-( Added: pypy/extradoc/talk/dls2006/image/flowlattice.dot ============================================================================== --- (empty file) +++ pypy/extradoc/talk/dls2006/image/flowlattice.dot Wed May 31 12:53:15 2006 @@ -0,0 +1,10 @@ +digraph lattice3 { + Variable -> "Constant(1)"; + d1 [label="...", color=white]; + Variable -> d1; + Variable -> "Constant(n)"; + d2 [label="...", color=white]; + Variable -> d2; + Variable -> "Constant([1,2,3])"; + Variable -> "Constant(instance of A)"; +} Modified: pypy/extradoc/talk/dls2006/image/flowlattice.pdf ============================================================================== Binary files. No diff available. Modified: pypy/extradoc/talk/dls2006/image/lattice1.pdf ============================================================================== Binary files. No diff available. Modified: pypy/extradoc/talk/dls2006/image/lattice2.pdf ============================================================================== Binary files. No diff available. From arigo at codespeak.net Wed May 31 12:55:12 2006 From: arigo at codespeak.net (arigo at codespeak.net) Date: Wed, 31 May 2006 12:55:12 +0200 (CEST) Subject: [pypy-svn] r27968 - pypy/extradoc/talk/dls2006 Message-ID: <20060531105512.B471910060@code0.codespeak.net> Author: arigo Date: Wed May 31 12:55:10 2006 New Revision: 27968 Modified: pypy/extradoc/talk/dls2006/draft.txt Log: Use the dot here, so that rst2pdf --debug will produce the pdf for us. Modified: pypy/extradoc/talk/dls2006/draft.txt ============================================================================== --- pypy/extradoc/talk/dls2006/draft.txt (original) +++ pypy/extradoc/talk/dls2006/draft.txt Wed May 31 12:55:10 2006 @@ -499,15 +499,7 @@ really an abstract domain. It handles objects that are placeholders. Its lattice order is shown in figure 5. -:: - - [figure 5: Variable - - / | \ \ - / | \ \ - / | \ \ - Constant(1) ... Constant(n) ... Constant([1,2,3]) ... Constant() ... - ] +.. graphviz:: image/flowlattice.dot This order is extremely simple, because most actual analysis is delayed to the next phase, the type inference engine. The objects are either From mwh at codespeak.net Wed May 31 12:57:50 2006 From: mwh at codespeak.net (mwh at codespeak.net) Date: Wed, 31 May 2006 12:57:50 +0200 (CEST) Subject: [pypy-svn] r27969 - pypy/extradoc/talk/dls2006/image Message-ID: <20060531105750.911461005A@code0.codespeak.net> Author: mwh Date: Wed May 31 12:57:46 2006 New Revision: 27969 Modified: pypy/extradoc/talk/dls2006/image/flowlattice.pdf Log: fix the bounding box -- with vim :) Modified: pypy/extradoc/talk/dls2006/image/flowlattice.pdf ============================================================================== Binary files. No diff available. From arigo at codespeak.net Wed May 31 13:04:34 2006 From: arigo at codespeak.net (arigo at codespeak.net) Date: Wed, 31 May 2006 13:04:34 +0200 (CEST) Subject: [pypy-svn] r27970 - pypy/extradoc/talk/dls2006 Message-ID: <20060531110434.C38DD1005A@code0.codespeak.net> Author: arigo Date: Wed May 31 13:04:26 2006 New Revision: 27970 Modified: pypy/extradoc/talk/dls2006/paper.tex Log: Yay. Only one XXX left Modified: pypy/extradoc/talk/dls2006/paper.tex ============================================================================== --- pypy/extradoc/talk/dls2006/paper.tex (original) +++ pypy/extradoc/talk/dls2006/paper.tex Wed May 31 13:04:26 2006 @@ -512,7 +512,8 @@ objects are the concrete Python objects of the various built-in types: lists, dictionaries, and so on. By opposition, the Flow Object Space is really an abstract domain. It handles objects that are placeholders. -Its lattice order is shown in figure \ref{flowlattice}. +Its lattice order (actually a join-semilattice only) is shown in +figure \ref{flowlattice}. \begin{figure*} \centering @@ -687,7 +688,7 @@ % Figures \ref{latticeoverall} and \ref{latticedetail} show how these types are ordered to form a lattice. We mostly use its structure of -[join-semilattice] only. +join-semilattice only. \begin{figure*} \centering @@ -808,28 +809,29 @@ the abstract interpretation engine that is critical for precision: the propagation of conditional types. Consider the following source code fragment: - +% \begin{verbatim} if isinstance(x, MyClass): f(x) else: g(x) \end{verbatim} - +% Although the type of \texttt{x} may be some parent class of \texttt{MyClass}, it can be deduced to be of the more precise type $Inst(MyClass)$ within the positive branch of the \texttt{if}. -(Remember that our graphs are in SSI form, which means that the +\footnote{Remember that our graphs are in SSI form, which means that the \texttt{x} inside each basic block is a different Variable with a -possibly different type as annotation.) XXX flow sensivity and SSA +possibly different type as annotation. Given that our type inference +is not flow-sensitive, SSI gives an advantage over SSA here.} This is implemented by introducing an extended family of types for boolean values: - +% $$ Bool(v_1: (t_1, f_1), v_2: (t_2, f_2), ...) $$ - +% where the $v_n$ are variables and $t_n$ and $f_n$ are types. The result of a check, like \texttt{isintance()} above, is typically annotated with such an extended $Bool$. The meaning of the type is as @@ -844,18 +846,21 @@ With the help of the above technique, we achieve a reasonable precision in small examples. For larger examples, a different, non-local -technique is required: the specialization of functions. XXX use 'polymorphism' +technique is required: the specialization of type-polymorphic functions. As described in the introduction, the most important downside of our approach is that automatic specialization is a potential -performance-killer. We \textit{do} support specialization, however: we can -generate several independently-annotated copies of the flow graphs of -certain functions. When annotating RPython programs, such -specialization does not happen automatically: we rely on hints provided -by the programmer in the source code, in the form of flags attached to -function objects. As we had this trade-off in mind when we wrote the -Python interpreter of PyPy, we only had to add a dozen or so hints in -the end. +performance-killer. So we decided that in the normal case, all calls to +a given function contribute to a single annotation of that function. +Inside the function graph, we propagate the \textit{join} of the types +of the actual parameters of the call sites. We \textit{do} support +specialization, however: we can generate several independently-annotated +copies of the flow graphs of certain functions. When annotating RPython +programs, such specialization does not happen automatically: we rely on +hints provided by the programmer in the source code, in the form of +flags attached to function objects. As we had this trade-off in mind +when we wrote the Python interpreter of PyPy, we only had to add a dozen +or so hints in the end. This does not mean that automatic specialization policies are difficult to implement. Indeed, the simpler lower-level type systems rely quite From mwh at codespeak.net Wed May 31 13:04:47 2006 From: mwh at codespeak.net (mwh at codespeak.net) Date: Wed, 31 May 2006 13:04:47 +0200 (CEST) Subject: [pypy-svn] r27971 - pypy/extradoc/talk/dls2006 Message-ID: <20060531110447.4C31010068@code0.codespeak.net> Author: mwh Date: Wed May 31 13:04:40 2006 New Revision: 27971 Added: pypy/extradoc/talk/dls2006/paper.bib - copied unchanged from r27967, pypy/extradoc/talk/dls2006/draft.bib Removed: pypy/extradoc/talk/dls2006/draft.bib Log: rename the .bib file From mwh at codespeak.net Wed May 31 13:10:39 2006 From: mwh at codespeak.net (mwh at codespeak.net) Date: Wed, 31 May 2006 13:10:39 +0200 (CEST) Subject: [pypy-svn] r27972 - pypy/extradoc/talk/dls2006 Message-ID: <20060531111039.BA52B1005A@code0.codespeak.net> Author: mwh Date: Wed May 31 13:10:36 2006 New Revision: 27972 Modified: pypy/extradoc/talk/dls2006/paper.bib pypy/extradoc/talk/dls2006/paper.tex Log: bibtex fixes, a little bibtex boilerplate and one \cite{}. Modified: pypy/extradoc/talk/dls2006/paper.bib ============================================================================== --- pypy/extradoc/talk/dls2006/paper.bib (original) +++ pypy/extradoc/talk/dls2006/paper.bib Wed May 31 13:10:36 2006 @@ -1,4 +1,5 @@ - at inproceedings{PlugType, % fix +% fix + at inproceedings{PlugType, author = {Bracha, Gilad }, journal = {Workshop on Revival of Dynamic Languages}, keywords = {language-implementation}, @@ -36,9 +37,9 @@ % SSA/SSI @mastersthesis{SSI, author = {C. S. Ananian}, - title = {The static single information form.} - school = { Massachusetts Institute of Technology} - year = {1999} + title = {The static single information form.}, + school = { Massachusetts Institute of Technology}, + year = {1999}, month = {September} } Modified: pypy/extradoc/talk/dls2006/paper.tex ============================================================================== --- pypy/extradoc/talk/dls2006/paper.tex (original) +++ pypy/extradoc/talk/dls2006/paper.tex Wed May 31 13:10:36 2006 @@ -1119,7 +1119,7 @@ and VM implementations, and Just-In-Time compilers. Scheme48 was a Scheme implementation using a restricted Scheme, PreScheme -[PreScheme], with static type inference based on Hindley-Milner. This is +\cite{kelsey-prescheme}, with static type inference based on Hindley-Milner. This is viable for Scheme as base language. Simplicity and portability across C platforms were its major goals. @@ -1203,4 +1203,7 @@ primitives and build everything on top of it; instead, we have been able to implement, so to speak, the right feature at the right level. +\bibliographystyle{abbrv} +\bibliography{paper} + \end{document} From arigo at codespeak.net Wed May 31 13:22:21 2006 From: arigo at codespeak.net (arigo at codespeak.net) Date: Wed, 31 May 2006 13:22:21 +0200 (CEST) Subject: [pypy-svn] r27973 - in pypy/extradoc/talk/dls2006: . image Message-ID: <20060531112221.C0E5610060@code0.codespeak.net> Author: arigo Date: Wed May 31 13:22:20 2006 New Revision: 27973 Added: pypy/extradoc/talk/dls2006/image/typesystems.dot pypy/extradoc/talk/dls2006/image/typesystems.pdf (contents, props changed) Modified: pypy/extradoc/talk/dls2006/draft.txt pypy/extradoc/talk/dls2006/paper.tex Log: Added the typesystem graph. Modified: pypy/extradoc/talk/dls2006/draft.txt ============================================================================== --- pypy/extradoc/talk/dls2006/draft.txt (original) +++ pypy/extradoc/talk/dls2006/draft.txt Wed May 31 13:22:20 2006 @@ -339,18 +339,9 @@ Type systems ------------ -The four levels that we considered so far are summarized in figure 2. +The four levels that we considered so far are summarized in figure 2: -:: - - [figure 2: RPython - / \ - / \ - LLTypeSystem OOTypeSystem - / - / - Raw addresses - ] +.. graphviz:: image/typesystems.dot The RPython level is a subset of Python, so the types mostly follow Python types, and the instances of these types are instances in the @@ -499,7 +490,10 @@ really an abstract domain. It handles objects that are placeholders. Its lattice order is shown in figure 5. -.. graphviz:: image/flowlattice.dot +:: + + graphviz:: image/flowlattice.dot + DISABLED because it needs manual adjusting of the bounding box This order is extremely simple, because most actual analysis is delayed to the next phase, the type inference engine. The objects are either Added: pypy/extradoc/talk/dls2006/image/typesystems.dot ============================================================================== --- (empty file) +++ pypy/extradoc/talk/dls2006/image/typesystems.dot Wed May 31 13:22:20 2006 @@ -0,0 +1,9 @@ +digraph lattice { + "RPython" [shape=octagon]; + "LL Type System" [shape=octagon]; + "OO Type System" [shape=octagon]; + "Raw Addresses" [shape=octagon]; + + "RPython" -> "LL Type System" -> "Raw Addresses"; + "RPython" -> "OO Type System"; +} Added: pypy/extradoc/talk/dls2006/image/typesystems.pdf ============================================================================== Binary file. No diff available. Modified: pypy/extradoc/talk/dls2006/paper.tex ============================================================================== --- pypy/extradoc/talk/dls2006/paper.tex (original) +++ pypy/extradoc/talk/dls2006/paper.tex Wed May 31 13:22:20 2006 @@ -350,14 +350,9 @@ \ref{fig_typesystems}. \begin{figure} -\begin{verbatim} - RPython - / \ - LLTypeSystem OOTypeSystem - / - Raw addresses -\end{verbatim} -\caption{Type systems, informally ordered by abstraction level} +\centering +\includegraphics[scale=0.667]{image/typesystems.pdf} +\caption{type systems; the arrows are transformations.} \label{fig_typesystems} \end{figure} From arigo at codespeak.net Wed May 31 13:34:22 2006 From: arigo at codespeak.net (arigo at codespeak.net) Date: Wed, 31 May 2006 13:34:22 +0200 (CEST) Subject: [pypy-svn] r27974 - pypy/extradoc/talk/dls2006 Message-ID: <20060531113422.05D2010060@code0.codespeak.net> Author: arigo Date: Wed May 31 13:34:20 2006 New Revision: 27974 Modified: pypy/extradoc/talk/dls2006/paper.tex Log: The \ss sign. Modified: pypy/extradoc/talk/dls2006/paper.tex ============================================================================== --- pypy/extradoc/talk/dls2006/paper.tex (original) +++ pypy/extradoc/talk/dls2006/paper.tex Wed May 31 13:34:20 2006 @@ -12,7 +12,7 @@ \alignauthor Armin Rigo\\ \affaddr{Heinrich-Heine-Universit?t D?sseldorf}\\ \affaddr{Institut f?r Informatik}\\ - \affaddr{Universit?tsstra?e 1}\\ + \affaddr{Universit?tsstra{\ss}e 1}\\ \affaddr{D-40225 D?sseldorf}\\ \affaddr{Deutschland}\\ \email{arigo at tunes.org} From pedronis at codespeak.net Wed May 31 14:29:26 2006 From: pedronis at codespeak.net (pedronis at codespeak.net) Date: Wed, 31 May 2006 14:29:26 +0200 (CEST) Subject: [pypy-svn] r27975 - pypy/extradoc/talk/dls2006 Message-ID: <20060531122926.A118D1005A@code0.codespeak.net> Author: pedronis Date: Wed May 31 14:29:25 2006 New Revision: 27975 Modified: pypy/extradoc/talk/dls2006/paper.tex Log: slight rephrasing Modified: pypy/extradoc/talk/dls2006/paper.tex ============================================================================== --- pypy/extradoc/talk/dls2006/paper.tex (original) +++ pypy/extradoc/talk/dls2006/paper.tex Wed May 31 14:29:25 2006 @@ -425,11 +425,12 @@ We mitigate the potential efficiency problem by wise choices and compromises for the domain used; the foremost example of this is that -our RPython type inference performs almost no polymorphic specialization -of functions. Another example is that unlike some schemes which follow -exact sets of concrete run-time classes, we only propagate a single -superclass per variable: the most precise common parent class. This -gives enough precision for our code generation purposes. +our RPython type inference performs almost no automatic specialization +of functions in the presence of polymorphic arguments. Another +example is that unlike some schemes which follow exact sets of +concrete run-time classes, we only propagate a single superclass per +variable: the most precise common parent class. This gives enough +precision for our code generation purposes. In the sequel, we give a more precise description of this process and justify our claim that good performance and enough precision can be From cfbolz at codespeak.net Wed May 31 14:35:49 2006 From: cfbolz at codespeak.net (cfbolz at codespeak.net) Date: Wed, 31 May 2006 14:35:49 +0200 (CEST) Subject: [pypy-svn] r27976 - in pypy/extradoc/talk/dls2006: . image Message-ID: <20060531123549.C9FE11005A@code0.codespeak.net> Author: cfbolz Date: Wed May 31 14:35:47 2006 New Revision: 27976 Added: pypy/extradoc/talk/dls2006/image/flowlattice.eps pypy/extradoc/talk/dls2006/image/lattice1.eps pypy/extradoc/talk/dls2006/image/lattice2.eps pypy/extradoc/talk/dls2006/image/typesystems.eps Modified: pypy/extradoc/talk/dls2006/paper.tex Log: use eps figures Added: pypy/extradoc/talk/dls2006/image/flowlattice.eps ============================================================================== --- (empty file) +++ pypy/extradoc/talk/dls2006/image/flowlattice.eps Wed May 31 14:35:47 2006 @@ -0,0 +1,2115 @@ +%!PS-Adobe-2.0 EPSF-1.2 +%%Title: lattice3 +%%Creator: dot version 2.2 (Tue Mar 22 18:02:44 UTC 2005) +%%CreationDate: 2006-05-31 14:15 flowlattice.ps +%%For: (carlson) Carl Friedrich Bolz +%%Pages: 1 +%%DocumentFonts: +%%BoundingBox: 35 35 595 145 +%%EndComments + +%%BeginProlog +%%BeginPreview: 560 110 8 1540 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000004444444488888888888888884444 +% 44440000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 0000000000000000000000000000000000000022448888bbeeffffeebbbbbbbbaa8888aabbbbbbbb +% eeffffeebb8888442200000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 000000000000000000000000000000226699ddffccbb887744110000000000000000000000000000 +% 000011447788bbddffdd996622000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 0000000000000000000000004488ccffcc8855110000000000000000000000000000000000000000 +% 0000000000000000115588ccffcc8844000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 0000000000000000001166ccff996622000000000000000000000000000000000000000000000000 +% 000000000000000000000000226699ffcc6611000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 000000000000003399eedd7711000000000000000000000000000000000000000000000000000000 +% 0000000000000000000000000000001177ddee993300000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000001199ff9944000000000000000000000000000000000000000000000000000000000000 +% 0000000000000000000000000000000000004499ff99110000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 0000000077eebb220000000000000000000000000000000000000000000000000000000000000000 +% 000000000000000000000000000000000000000022bbee7700000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 000033dddd5500000000000000000000000000000000000000000000000000000000000000000000 +% 0000000000000000000000000000000000000000000055dddd330000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 0033ee99110000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000001199ee3300000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 66ff6600000000000000000000000000000000000000000000000000000000000000000000000000 +% 0000000000000000000000000000000000000000000000000077ff66000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000066 +% ff660000000000000000000000000000000000000000000000000000000000000000000000000000 +% 000000000000000000000000000000000000000000000000000066ff660000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 000000000000000000000000000000000000000000000000000000000000000000000000000022ee +% 55000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000055ee2200000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 0000000000000000000000000000000000000000000000000000000000000000000000000000bbaa +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000aabb00000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 0000000000000000000000000000000000000000000000000000000000000000000000000077ee11 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000011 +% 6600000000001166000000000000000000000000000000000000000011ee66000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000dd6600 +% 000000000000000000bbffffff000000ffffbb0000000000000000000000bb000000000000000055 +% ff000000000033ff00000000000000000000000000000000000000000066dd000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000011ff2200 +% 00000000000000000011ccff0000000022cc11000000000000000000000000000000000000000000 +% ff000000000000ff00000000000000000000000000000000000000000022ff110000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000044dd0000 +% 0000000000000000000033ff66000000665500000000000000000000000044000000000000000000 +% ff000000000000ff00000000000000000000000000000000000000000000dd440000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000088aa0000 +% 000000000000000000000099dd000000bb000088eeff880055dd44aa9944ff00000088eeff880000 +% ff99ffdd330000ff00000066ddffbb110000000000000000000000000000aa880000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000088aa0000 +% 000000000000000000000022ff660066660000aa0033ff0000ff00000000ff000000aa0033ff0000 +% ff440099bb0000ff000044ffffffff880000000000000000000000000000aa880000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000044dd0000 +% 00000000000000000000000099dd11cc000000001166ff0000ff00000000ff000000001166ff0000 +% ff000011ff0000ff00008877000000000000000000000000000000000000dd440000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000011ff2200 +% 00000000000000000000000022ffaa88000000333300ff0000ff00000000ff000000333300ff0000 +% ff000000ee0000ff0000aa99000000220000000000000000000000000022ff110000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000dd6600 +% 0000000000000000000000000099ee11000000ee3344ff1111ff22000011ff220000ee3344ff1100 +% ff220088880011ff220066ff550044660000000000000000000000000066dd000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 0000000000000000000000000000000000000000000000000000000000000000000000000077ee11 +% 00000000000000000000000000229900000000aaee88ddddffffff8800bbffff8800aaee88dddd22 +% 99ffff880000bbffff880088ffee880000000000000000000000000011ee66000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 0000000000000000000000000000000000000000000000000000000000000000000000000000bbaa +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000aabb00000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 000000000000000000000000000000000000000000000000000000000000000000000000000022ee +% 55000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000055ee2200000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000066 +% ff660000000000000000000000000000000000000000000000000000000000000000000000000000 +% 000000000000000000000000000000000000000000000000000066ffb84400000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 66ff6600000000000000000000000000000000000000000000000000000000000000000000000000 +% 0000000000000000000000000000000000000000000000000077ff70aaeeffcc8866220000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 004ef699110000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000001199ee33000000226688ccffeeaa884400 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000003388 +% ccffd7e0dd5500000000000000000000000000000000000000000000000000000000000000000000 +% 0000000000000000000000000000000000000000000055dddd330000000000000000004488bbeeff +% cc885522000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000004488ddffaa +% 6611000077eebb220000000000000000000000000000000000000000000000000000000000000000 +% 000000000000000000000000000000000000000022bbee7700000000000000000000000000000033 +% 6699ccffddaa77440000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000005599eeee99551100 +% 00000000001199ffc244000000000000000000000000000000000000000000000000000000000000 +% 0000000000000000000000000000000000004499ffc2110000000000000000000000000000000000 +% 000000114488bbeeffbb885511000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 000000000000000000000000000000000000000000000000000000001166aaeedd99550000000000 +% 00000000000066e4f2f1dd7711000000000000000000000000000000000000000000000000000000 +% 0000000000000000000000000000001177ddee994edddd8811000000000000000000000000000000 +% 0000000000000000336699ddffdd9977330000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 000000000000000000000000000000000000000000000000002277aaffdd88330000000000000000 +% 0000000044ccee88001166ccff996622000000000000000000000000000000000000000000000000 +% 000000000000000000000000226699ffcc661100000066ddee881100000000000000000000000000 +% 000000000000000000000000115588bbffeebb884411000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 000000000000000000000000000000000000000000002277ccffcc77330000000000000000000000 +% 000044bbee881100000000004488ccffcc8855110000000000000000000000000000000000000000 +% 0000000000000000115588ccffcc8833000000000000000055bbee88220000000000000000000000 +% 00000000000000000000000000000000004477aaeeffcc8866220000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 000000000000000000000000000000000000003388ddffaa77220000000000000000000000000000 +% 22bbff881100000000000000000000226699ddffccbb987744110000000000000000000000000000 +% 000011447798bbddffdd9966220000000000000000000000000044bbff9922000000000000000000 +% 000000000000000000000000000000000000000000226688ccffddaa774400000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 000000000000000000000000000000005599ddffaa66110000000000000000000000000000002299 +% ff992200000000000000000000000000000000224490f8d2eeffffeebbbbbbbbaa8888aabbbbbbbb +% eeffffeed2f89044220000000000000000000000000000000000000044aaff992200000000000000 +% 00000000000000000000000000000000000000000000000000114488bbffffbb8855110000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 000000000000000000000000115599eeee995500000000000000000000000000000000001199ffaa +% 22000000000000000000000000000000000000000088bb0000004444444488888888888888884444 +% 4444000000bbaa00000000000000000000000000000000000000000000002299ffaa440000000000 +% 000000000000000000000000000000000000000000000000000000000000337799ddffcc99662200 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 0000000000000000001166aaffdd88440000000000000000000000000000000000001188eebb4400 +% 000000000000000000000000000000000000000044ff330000000000000000000000000000000000 +% 000000000022ee550000000000000000000000000000000000000000000000002299ffbb44000000 +% 00000000000000000000000000000000000000000000000000000000000000000000225588ccffee +% aa774400000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 0000000000002277bbffcc8833000000000000000000000000000000000000001188eebb44000000 +% 0000000000000000000000000000000000000000cc88000000000000000000000000000000000000 +% 00000000000077ee11000000000000000000000000000000000000000000000000002288eebb5500 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000044 +% 88bbeeffbb8855110000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 0000003388ccffcc772200000000000000000000000000000000000000000066eedd550000000000 +% 0000000000000000000000000000000000000077dd11000000000000000000000000000000000000 +% 00000000000000bbaa0000000000000000000000000000000000000000000000000000001188eedd +% 66000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 000000337799ddffcc99662200000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 3388ddffaa66110000000000000000000000000000000000000000000066dddd6600000000000000 +% 00000000000000000000000000000000000011ee5500000000000000000000000000000000000000 +% 0000000000000022ee55000000000000000000000000000000000000000000000000000000001188 +% dddd6600000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000225588ccffeeaa7744000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 000000000000000000000000000000000000000000000000000000000000000000000000005599ee +% ee996611000000000000000000000000000000000000000000000044ccee77000000000000000000 +% 000000000000000000000000000000000000aabb0000000000000000000000000000000000000000 +% 000000000000000077ee110000000000000000000000000000000000000000000000000000000000 +% 0066ddee881100000000000000000000000000000000000000000000000000000000000000000000 +% 0000000000000000000000114488bbffffbb88551100000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 0000000000000000000000000000000000000000000000000000000000000000001166aaeedd9955 +% 0000000000000000000000000000000000000000000000000044bbee881100000000000000000000 +% 000000000000000000000000000000000044ff220000000000000000000000000000000000000000 +% 000000000000000000bb880000000000000000000000000000000000000000000000000000000000 +% 00000066ddee88110000000000000000000000000000000000000000000000000000000000000000 +% 000000000000000000000000000000003377aaddffcc886622000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 0000000000000000000000000000000000000000000000000000000000002277aaffdd8833000000 +% 000000000000000000000000000000000000000000000022aaff8811000000000000000000000000 +% 0000000000000000000000000000000000dd88000000000000000000000000000000000000000000 +% 00000000000000000033ff4400000000000000000000000000000000000000000000000000000000 +% 000000000055bbee8822000000000000000000000000000000000000000000000000000000000000 +% 0000000000000000000000000000000000000000226688ccffddaa77330000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 0000000000000000000000000000000000000000000000000000002277ccffcc7733000000000000 +% 0000000000000000000000000000000000000000002299ff99220000000000000000000000000000 +% 0000000000000000000000000000000088dd00000000000000000000000000000000000000000000 +% 0000000000000000000088dd11000000000000000000000000000000000000000000000000000000 +% 0000000000000044bbff992200000000000000000000000000000000000000000000000000000000 +% 000000000000000000000000000000000000000000000000115588bbffeebb884400000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 0000000000000000000000000000000000000000000000003388ddffaa7722000000000000000000 +% 000000000000000000000000000000000000001188ffbb2200000000000000000000000000000000 +% 00000000000000000000000000000022ee4400000000000000000000000000000000000000000000 +% 0000000000000000000000cc88000000000000000000000000000000000000000000000000000000 +% 0000000000000000004499ff99330000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000004477aaeeffcc8855110000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 0000000000000000000000000000000000000000005599ddeeaa6611000000000000000000000000 +% 00000000000000000000000000000000001188eebb44000000000000000000000000000000000000 +% 000000000000000000000000000000bbaa0000000000000000000000000000000000000000000000 +% 000000000000000000000033ff440000000000000000000000000000000000000000000000000000 +% 00000000000000000000002299ffbb44000000000000000000000000000000000000000000000000 +% 000000000000000000000000000000000000000000000000000000000000000000226699ddffdd99 +% 66330000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 0000000000000000000000000000000000116699eeee995500000000000000000000000000000000 +% 0000000000000000000000000000000066eedd550000000000000000000000000000000000000000 +% 000000000000000000000000000055ee220000000000000000000000000000000000000000000000 +% 00000000000000000000000088dd1100000000000000000000000000000000000000000000000000 +% 000000000000000000000000002299eebb4400000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000115588 +% bbffeeaa884400000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000002266aaffdd884400000000000000000000000000000000000000 +% 000000000000000000000000000066dddd6600000000000000000000000000000000000000000000 +% 0000000000000000000000000011dd77000000000000000000000000000000000000000000000000 +% 00000000000000000000000000cc8800000000000000000000000000000000000000000000000000 +% 0000000000000000000000000000001188eedd660000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00004488bbeeffbb8855110000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000002277ccffcc883300000000000000000000000000000000000000000000 +% 00000000000000000000000044ccee88000000000000000000000000000000000000000000000000 +% 0000000000000000000000000088cc00000000000000000000000000000000000000000000000000 +% 0000000000000000000000000033ff33000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000001188eedd66000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 000000000000337799ddffcc88662200000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000003388ddffbb772200000000000000000000000000000000000000000000000000 +% 0000000000000000000044bbee881100000000000000000000000000000000000000000000000000 +% 00000000000000000000000033ff3300000000000000000000000000000000000000000000000000 +% 000000000000000000000000000088cc000000000000000000000000000000000000000000000000 +% 000000000000000000000000000000000000000066dddd7711000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000226688ccffddaa7733000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000005599ddffaa661100000000000000000000000000000000000000000000000000000000 +% 00000000000000002299ff9911000000000000000000000000000000000000000000000000000000 +% 000000000000000000000000cc880000000000000000000000000000000000000000000000000000 +% 000000000000000000000000000011dd880000000000000000000000000000000000000000000000 +% 0000000000000000000000000000000000000000000066ddee881100000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 0000000000000000000000000000115588bbffeebb88440000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00116699eeee99550000000000000000000000000000000000000000000000000000000000000000 +% 0000000000002299ff99220000000000000000000000000000000000000000000000000000000000 +% 000000000000000000000077dd110000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000044ff3300000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000066bbee88220000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 000000000000000000000000000000000000004477aaeeffbb885511000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000002266 +% aaffdd88440000000000000000000000000000000000000000000000000000000000000000000000 +% 000000001188eebb3300000000000000000000000000000000000000000000000000000000000000 +% 0000000000000000000022ee55000000000000000000000000000000000000000000000000000000 +% 0000000000000000000000000000000088cc00000000000000000000000000000000000000000000 +% 000000000000000000000000000000000000000000000000000044bbff9922000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 0000000000000000000000000000000000000000000000336699ddffdd9966220000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000002277ccffcc +% 88330000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00001188eebb44000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000bbaa00000000000000000000000000000000000000000000000000000000 +% 0000000000000000000000000000000011dd88000000000000000000000000000000000000000000 +% 0000000000000000000000000000000000000000000000000000000044bbff992200000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 000000000000000000000000000000000000000000000000000000225588ccffeeaa773300000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000003388ddffbb772200 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 0066dddd550000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000055ee2200000000000000000000000000000000000000000000000000000000 +% 000000000000000000000000000000000044ff330000000000000000000000000000000000000000 +% 0000000000000000000000000000000000000000000000000000000000002299ffaa440000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000004488bbffffbb8844 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000005599ddeeaa661100000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000066 +% dddd6600000000000000000000000000000000000000000000000000000000000000000000000000 +% 000000000000000011ee770000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000088bb0000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000002299ffbb44000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 0000000000000000000000000000000000000000000000000000000000000000000000003377aaee +% ffcc8855110000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 000000000000000000000000000000000000000000000000001166aaeeee99550000000000000000 +% 0000000000000000000000000000000000000000000000000000000000000000000000000044bbee +% 88000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 000000000000000088bb000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000011ee7700000000000000000000000000000000000000 +% 000000000000000000000000000000000000000000000000000000000000000000002288eebb5500 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 226699ddffdd99662200000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 000000000000000000000000000000000000000000002277aaffdd88330000000000000000000000 +% 000000000000000000000000000000000000000000000000000000000000000000000044bbee8811 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 0000000000000044ff33000000000000000000000000000000000000000000000000000000000000 +% 0000000000000000000000000000000000000055ee22000000000000000000000000000000000000 +% 0000000000000000000000000000000000000000000000000000000000000000000000001188eedd +% 66000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000115588ccffeeaa7744000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 000000000000000000000000000000000000003377ccffcc77330000000000000000000000000000 +% 0000000000000000000000000000000000000000000000000000000000000000002299ff99110000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000cc8800000000000000000000000000000000000000000000000000000000000000 +% 0000000000000000000000000000000000000000aabb000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000001188 +% dddd6600000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 0000000000000000004488bbffffbb88441100000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 000000000000000000000000000000004488ddffaa66220000000000000000000000000000000000 +% 000000000000000000000000000000000000000000000000000000000000002299ff992200000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000088dd1100000000000000000000000000000000000000000000000000000000000000 +% 000000000000000000000000000000000000000011ee770000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 0066ddee881100000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 000000000000000000000000003377aaeeffcc885522000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 000000000000000000000000005599eeee9966110000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000001188eebb44000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 002266000022ff440000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000055ee2200000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000066ddee88110000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 0000000000000000000000000000000000226699ddffdd9966330000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 0000000000000000001166aaffdd8855000000000000000000000000000000000000000000000000 +% 0000000000000000000000000000000000000000000000000000001188eebb440000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00bbffeb66bb99000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000aabb00006622000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 000000000055bbee8822000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 000000000000000000000000000000000000000000115588bbffeeaa774400000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 0000000000002277ccffcc8833000000000000000000000000000000000000000000000000000000 +% 000000000000000000000000000000000000000000000000000066dddd6600000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00ebfffffdfe70000000000000000000000000000000000000000000000000000000000000000000 +% 0000000000000000000000000000000000000000000011ee99ebffbb000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 0000000000000044bbff992200000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000004488bbeeffbb8844110000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 0000003388ddffbb7722000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000066dddd66000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 11fffffffffffbeb2200000000000000000000000000000000000000000000000000000000000000 +% 0000000000000000000000000000000000000000000066eefbffffeb000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000044bbff99220000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 0000000000000000000000000000000000000000000000000000000000003377aaddffcc88552200 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 5599ddeeaa6611000000000000000000000000000000000000000000000000000000000000000000 +% 0000000000000000000000000000000000000000000044ddee880000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 44f6ffffffffffff4400000000000000000000000000000000000000000000000000000000000000 +% 000000000000000000000000000000000000000022ebfbffffffffff110000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000002299ff9933000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000226699ccffdd +% 99663300000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 0000000000000000000000000000000000000000000000000000000000000000000000001166aaee +% ee995500000000000000000000000000000000000000000000000000000000000000000000000000 +% 000000000000000000000000000000000000000044bbee8811000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 88fffffffffff5330000000000000000000000000000000000000000000000000000000000000000 +% 000000000000000000000000000000000000000044fffffffffffff6440000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 000000000000000000000000002299ffbb4400000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000001155 +% 88bbffeeaa7744000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 0000000000000000000000000000000000000000000000000000000000000000002277bbffdd8833 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000033bbff88110000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% bbfffffffaeb33000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000033f5ffffffffff880000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 0000000000000000000000000000002299ffbb440000000000225500000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 0000004488bbeeffbb88441100000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 0000000000000000000000000000000000000000000000000000000000003388ccffcc7722000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 000000000000000000000000000000002299ff992200000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% ebfffffcd71100000000000000000000000000000000000000000000000000000000000000000000 +% 0000000000000000000000000000000000000000000033ebfaffffffbb0000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000001188eebb66000000ebff80000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 000000000000003377aaddffcc885522000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 0000000000000000000000000000000000000000000000000000005599ddffaa6611000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000002299ff9922000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000011 +% fffff9bb110000000000000000000000000000000000000000000000000000000000000000000000 +% 000000000000000000000000000000000000000000000011d7fcffffeb0000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 000000000000000000000000000000000000001188eedd6666fbfffca00000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 0000000000000000000000226699ccffdd9966330000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000001166aaeedd995500000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 0000000000332200000000001188ffbb330000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000044 +% fffca000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000011bbf9ffff1100000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 0000000000000000000000000000000000000000001188ddfdfffffff9bb11000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 000000000000000000000000000000115588bbffeeaa884400000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% +% 00000000000000000000000000000000000000000000000000000000000000000000000000444444 +% 44447788888888888888887744444444440000000000000000000000000000000000000000000000 +% 00000000000000000000552200000000000000002277bbffcc883300000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 0000000033ffeb0000001188eebb4400000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000444444444477888888888888888877444444444488 +% ff800000000000000000000000000000000000000000000000000000000000000000000000000000 +% 0000000000000000000000000000000000000000000000000000a0fcff4400000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 000000000000000000000000000000000000000000000066fdfffffffffcd7110000000000000000 +% 00000000000000000000000011444444444444558888888888888888888888885544444444444411 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000004488bbeeffbb8855110000000000000000000022 +% 66000000000000000000000000000000000000000000000000000000000000000000000000000000 +% +% 000000000000000000000000000000000000000000000000000000000044448888bbbbffffffffbb +% bbbbbbbbbb99888899bbbbbbbbbbccffffffffbbbb88884444000000000000000000000000000000 +% 000000000000000011b6ffd700000000004488ddffbb772200000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000033f5fffb660088eecc44000000000000000000000000000000000000000000000000000000 +% 000000000000000000000044448888bbbbffffffffbbbbbbbbbbbb99888899bbbbbbbbbbccffffff +% ffbbbb88884444000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000080ff8800000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 0000000000000000000000000000000000000000000000ebfffffffffffffaeb3300000000000000 +% 0000444455888899bbbbffffffffffddbbbbbbbbbbbbbbbb88888888bbbbbbbbbbbbbbbbddffffff +% ffffbbbb998888554444000000000000000000000000000000000000000000000000000000000000 +% 0000000000000000000000000000000000000000000000003377aaddffcc886622000000000000bb +% ffe64400000000000000000000000000000000000000000000000000000000000022444444888888 +% +% 000000000000000000000000000000000000000000000000337799ccffffbbbb8888554411000000 +% 00000000000000000000000000000000001144558888bbbbffffcc99773300000000000000000000 +% 0000000000000055f6faffff22116699eeee99661100000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 000011ebffffffeedddd660000000000000000000000000000000000000000000000000000000000 +% 000000000000337799ccffffbbbb8888554411000000000000000000000000000000000000000011 +% 44558888bbbbffffcc99773300000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000441100000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 0000000000000000000000000000000000000000000066fffffffffffffffffff5330011447788bb +% ddffffddbbbb88888844443300000000000000000000000000000000000000000000000000000000 +% 334444888888bbbbddffffddbb887744110000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000226688ccffdd9977330000dd +% fffffbc43300000000000000000000000000000000000000002244668899bbddffffffddbbbbbb88 +% +% 00000000000000000000000000000000000000005588bbffffbb8855220000000000000000000000 +% 00000000000000000000000000000000000000000000000000225588bbffffbb8855000000000000 +% 000000000011b6fbfffffff9dbffdd88440000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 0011d7fafffffffba300000000000000000000000000000000000000000000000000000000000000 +% 00005588bbffffbb8855220000000000000000000000000000000000000000000000000000000000 +% 00000000000000225588bbffffbb8855000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 0000000000000000000000000000000000000000000022a7cdcdf6fffffffcf8fffff3ffeebb8877 +% 44220000000000000000000000000000000000000000000000000000000000000000000000000000 +% 0000000000000000000022447788bbeeffeebb887733000000000000000000000000000000000000 +% 0000000000000000000000000000000000000000000000000000000000000000115588bbffeeaaff +% ffffffffffa0220000000000000000000000336688aabbeeffffddbbaa8877443300000000000000 +% +% 00000000000000000000000000000000005599eeee99663300000000000000000000000000000000 +% 000000000000000000000000000000000000000000000000000000000000337799eeee9955000000 +% 0000000055f6faffffffffffea220000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00bbfcffffffffffeb00000000000000000000000000000000000000000000000000000000000055 +% 99eeee99663300000000000000000000000000000000000000000000000000000000000000000000 +% 000000000000000000000000337799eeee9955000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000003377aaf3ffd2c8c0501100000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 0000000000000000000000000000000011447788bbffeeaa77330000000000000000000000000000 +% 0000000000000000000000000000000000000000000000000000000000000000000000000044a0ff +% fffffffffffbf8901100000011447799ccffffbb9988664422000000000000000000000000000000 +% +% 000000000000000000000000000066aaeedd88550000000000000000000000000000000000000000 +% 000000000000000000000000000000000000000000000000000000000000000000005588ddee9966 +% 000011b6fbffffffffffffffff220000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% a0f9ffffffffffffff66000000000000000000000000000000000000000000000000000066aaeedd +% 88550000000000000000000000000000000000000000000000000000000000000000000000000000 +% 000000000000000000000000000000005588ddee9966000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 000000000000000000000000000000000000000000003388bbeeffbb884400000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 000000000000000000000000000000000000000000004488bbffeeaa883300000000000000000000 +% 000000000000000000000000000000000000000000000000000000000000000000000000000055f5 +% fffffffffffffffff998aaddffeebb88663300000000000000000000000000000000000000000000 +% +% 00000000000000000000001177dddd88330000000000000000000000000000000000000000000000 +% 000000000000000000000000000000000000000000000000000000000000000000000000003388dd +% dd7af7fffffffffffffffffffd770000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000080 +% fcfffffffff6ffebbb2200000000000000000000000000000000000000000000001177dddd883300 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 000000000000000000000000000000000000003388dddd6611000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 000000000000000000000000000000000000002288ddffaa88440000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000004488aaffdd882200000000000000 +% 000000000000000000000000000000000000000000000000000000000000000000000000000088ff +% ffedfffffffff6fff4b6884411000000000000000000000000000000000000000000000000000000 +% +% 0000000000000000001188eedd660000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 66e0f8c8908888888888888888330000000000000000000000000000000000000000000000000000 +% 000000000000000000000000000000000000000000000000000000000000000000000000000044ff +% ffffebbb8844110000000000000000000000000000000000000000000000001188eedd6600000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 0000000000000000000000000000000000000000000066ddee881100000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 000000000000000000000000000000001177ccffaa66110000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000001166aaffcc771100000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000003388 +% a09bc1ffeeaa66220000000000000000000000000000000000000000000000000000000000000000 +% +% 000000000000000088eebb6600000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 000066ccee8800000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000001188 +% 44110000000000000000000000000000000000000000000000000000000088eebb66000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000066ccee88000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 000000000000000000000000000044aaffcc77220000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000002277ccffaa440000 +% 000000000000000000000000000000000000000000000000000000000000000000000000003399dd +% ffbb8833000000000000000000000000000000000000000000000000000000000000000000000000 +% +% 00000000000022ccdd44000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 0000000044ddcc220000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 0000000000000000000000000000000000000000000000000000000022ccdd440000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 000000000000000000000000000000000000000000000000000044ddcc2200000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000022aaff88220000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000002299ffaa22 +% 000000000000000000000000000000000000000000000000000000000000000000000066ccff9955 +% 11000000000000000000000000000000000000000000000000000000000000000000000000000000 +% +% 000000000066ee991100000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000001199ee6600000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000066ee9911000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 0000000000000000000000000000000000000000000000000000001199ee66000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 000000000000000000001199ff992200000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 000000000000000000000000000000000000000000000000000000000000000000000000002299ff +% 99110000000000000000000000000000000000000000000000000000000000002288eedd77110000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% +% 0000000099ee66000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 0000000000000066ee99000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 000000000000000000000000000000000000000000000000000099ee660000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 000000000000000000000000000000000000000000000000000000000066ee990000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000088eebb33000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000033 +% bbee8800000000000000000000000000000000000000000000000000000033bbffaa550000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% +% 00000088dd2200000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 000000000000000022dd880000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 0000000000000000000000000000000000000000000000000088dd22000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000022dd8800000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 000000000000000099ee440000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 0044ee990000000000000000000000000000000000000000000000000077ff992200000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% +% 000066ee330000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000033ff5500000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000066ee3300000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 0000000000000000000000000000000000000000000000000000000000000033ff55000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 0000000000000099ee33000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 000033ee990000000000000000000000000000000000000000000011aaee55000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% +% 0033ee66000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000011110000440000003300000000 +% 0000000000000000000066ee33000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 000000000000000000000000000000000000000000000033ee660000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 000000000000000000111100000000000033000000000000000000000000000066ee330000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000099dd3300000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000111100000000000000 +% 44000000000000000000000000000000000000000000000000000000003300000000000000000000 +% 00000033dd99000000000000000000000000000000000000000044eebb1100000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% +% 00aaaa000000000000000000000000001199eeffdd88770000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000003366001166ff0000000077110000 +% 0000000000000000000000aaaa000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 0000000000000000000000000000000000000000000000aaaa000000000000000000000000001199 +% eeffdd88770000000000000000000000000000000000000000000000000000000000000000000000 +% 000000000000000033660000000000000000771100000000000000000000000000aaaa0000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 000000000066dd110000000000000000000000001199eeffdd887700000000000000000000000000 +% 000000000000000000000000000000000000000000000000000000000000336600ffffff44001166 +% ff0000000000000066ddffbb33000000000055ddffdd660088ffff00000077110000000000000000 +% 0000000011dd6600000000000000000000000000000000000022ff77000000000000000000000000 +% 1199eeffdd8877000000000000000000000000000000000000000000000000000000000000000000 +% +% 00ee4400000000000000000000000011cc88110033aa880000000000000000000000000000000000 +% 00000000660000000000000000000000000000000066000000008800000000ff0000000000880000 +% 000000000000000000000044ee000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 0000000000000000000000000000000000000000000000ee4400000000000000000000000011cc88 +% 110033aa880000000000000000000000000000000000000000006600000000000000000000000000 +% 00000066000000008800000000000000000000880000000000000000000000000044ee0000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 0000000000cc7700000000000000000000000011cc88110033aa8800000000000000000000000000 +% 000000000000000066000000000000000000000000000000006600000000880000ff110000000000 +% ff0000000000004477001199dd000000002277110077ee000011ff00000000880000000000000000 +% 000000000077cc00000000000000000000000000000000000088bb00000000000000000000000011 +% cc88110033aa88000000000000000000000000000000000000000000660000000000000000000000 +% +% 33ff0000000000000000000000000099880000000000990000000000000000000000000000000000 +% 00000000dd00000000000000000000000000000000dd000000665500000000ff0000000000774400 +% 000000000000000000000000ff330000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 0000000000000000000000000000000000000000000033ff00000000000000000000000000998800 +% 0000000099000000000000000000000000000000000000000000dd00000000000000000000000000 +% 000000dd000000665500000000000000000000774400000000000000000000000000ff3300000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 0000000022ff22000000000000000000000000998800000000009900000000000000000000000000 +% 0000000000000000dd00000000000000000000000000000000dd00000066550000ff000000000000 +% ff0000000000002200000011ff000000000000000000cc000000ff00000000774400000000000000 +% 000000000022ff220000000000000000000000000000000011ee5500000000000000000000000099 +% 88000000000099000000000000000000000000000000000000000000dd0000000000000000000000 +% +% 77aa00000000000000000000000000ee220000000000000011bbffbb110044cc99ddff88000088ff +% ff660088ffff880088eeff880044cc99ddff880088ffff8800bb2200000000ff000000000033aa00 +% 000000000000000000000000bb770000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 0000000000000000000000000000000000000000000077aa00000000000000000000000000ee2200 +% 00000000000011bbffbb110044cc99ddff88000088ffff660088ffff880088eeff880044cc99ddff +% 880088ffff8800bb220044cc99ddff8800000033aa00000000000000000000000000bb7700000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 0000000077cc00000000000000000000000000ee220000000000000011bbffbb110044cc99ddff88 +% 000088ffff660088ffff880088eeff880044cc99ddff880088ffff8800bb220000ff000000000000 +% ff0000000000000000000011bb00000000000000006611000000ff0000000033aa00000000000000 +% 000000000000cc770000000000000000000000000000000066dd00000000000000000000000000ee +% 220000000000000011bbffbb110044cc99ddff88000088ffff660088ffff880088eeff880044cc99 +% +% 77aa00000000000000000000000000ff0000000000000000aa660099aa0000ff660033ff0000ff22 +% 11440000ff000000aa0033ff0000ff660033ff0000ff000000ff0000000000ff000000000000ee00 +% 000000000000000000000000bb770000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 0000000000000000000000000000000000000000000077aa00000000000000000000000000ff0000 +% 000000000000aa660099aa0000ff660033ff0000ff2211440000ff000000aa0033ff0000ff660033 +% ff0000ff000000ff000000ff660033ff00000000ee00000000000000000000000000bb7700000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 0000000077cc00000000000000000000000000ff0000000000000000aa660099aa0000ff660033ff +% 0000ff2211440000ff000000aa0033ff0000ff660033ff0000ff000000ff000000ff000000000000 +% ff00000000000000000000883300000000000044aaff77000000ff0000000000ee00000000000000 +% 000000000000cc770000000000000000000000000000000066dd00000000000000000000000000ff +% 0000000000000000aa660099aa0000ff660033ff0000ff2211440000ff000000aa0033ff0000ff66 +% +% 33ff00000000000000000000000000ee2200000000000000ff000011ff0000ff000000ff00005577 +% 11000000ff000000001166ff0000ff000000ff0000ff000000ff0000000000ff000000000000ff00 +% 000000000000000000000000ff330000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 0000000000000000000000000000000000000000000033ff00000000000000000000000000ee2200 +% 000000000000ff000011ff0000ff000000ff0000557711000000ff000000001166ff0000ff000000 +% ff0000ff000000ff000000ff000000ff00000000ff00000000000000000000000000ff3300000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 0000000022ff22000000000000000000000000ee2200000000000000ff000011ff0000ff000000ff +% 0000557711000000ff000000001166ff0000ff000000ff0000ff000000ff000000ff000000000000 +% ff000000000000000000335500000000000000000077ee000000ff0000000000ff00000000000000 +% 000000000022ff220000000000000000000000000000000011ee55000000000000000000000000ee +% 2200000000000000ff000011ff0000ff000000ff0000557711000000ff000000001166ff0000ff00 +% +% 00ee44000000000000000000000000998800000000000000ff220000ff0000ff000000ff00001111 +% 77660000ff000000333300ff0000ff000000ff0000ff000000ff0000000000ff000000000000ff00 +% 000000000000000000000044ee000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 0000000000000000000000000000000000000000000000ee44000000000000000000000000998800 +% 000000000000ff220000ff0000ff000000ff0000111177660000ff000000333300ff0000ff000000 +% ff0000ff000000ff000000ff000000ff00000000ff00000000000000000000000044ee0000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 0000000000cc77000000000000000000000000998800000000000000ff220000ff0000ff000000ff +% 0000111177660000ff000000333300ff0000ff000000ff0000ff000000ff000000ff000000000000 +% ff000000000000000033550000000000000000000000ff000000ff0000000000ff00000000000000 +% 000000000077cc00000000000000000000000000000000000088bb00000000000000000000000099 +% 8800000000000000ff220000ff0000ff000000ff0000111177660000ff000000333300ff0000ff00 +% +% 00aaaa00000000000000000000000022ee88220011557700aa990077990011ff110011ff11009900 +% 33ff0000ff110000ee3344ff1111ff110011ff1100ff110000bb2200000033ff110000000033aa00 +% 0000000000000000000000aaaa000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000551100005511005511000000000000000000000000000000000000 +% 0000000000000000000000000000000000000000000000aaaa00000000000000000000000022ee88 +% 220011557700aa990077990011ff110011ff1100990033ff0000ff110000ee3344ff1111ff110011 +% ff1100ff110000bb220011ff110011ff11000033aa000000000000000000000000aaaa0000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000005511000055 +% 11005511000000000000000000000000000000000000000000000000000000000000000000000000 +% 000000000066dd11000000000000000000000022ee88220011557700aa990077990011ff110011ff +% 1100990033ff0000ff110000ee3344ff1111ff110011ff1100ff110000bb220000ff000000000033 +% ff11000077110000335500001155007711000000002299000000ff0000000033aa00000000000000 +% 0000000011dd6600000000000000000000000000000000000022ff77000000000000000000000022 +% ee88220011557700aa990077990011ff110011ff1100990033ff0000ff110000ee3344ff1111ff11 +% +% 0033ee660000000000000000000000002299eeffdd88000011bbffbb1100bbffff44ffffbb00ddff +% ee770000aaff7700aaee88ddddc4ffff44ffffbb00aaff77006666000044ffffff88000000666600 +% 0000000000000000000066ee33000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000ee770000ee7700ee77000000000000000000000000000000000000 +% 000000000000000000000000000000000000000000000033ee660000000000000000000000002299 +% eeffdd88000011bbffbb1100bbffff44ffffbb00ddffee770000aaff7700aaee88ddddc4ffff44ff +% ffbb00aaff7700666600bbffff44ffffbb00006666000000000000000000000066ee330000000000 +% 0000000000000000000000000000000000000000000000000000000000000000000000ee770000ee +% 7700ee77000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000099dd3300000000000000000000002299eeffdd88000011bbffbb1100bbffff44ffff +% bb00ddffee770000aaff7700aaee88ddddc4ffff44ffffbb00aaff770066660000ff0000000044ff +% ffff8833ffaa0033eeffffffff2233ffaa55ee66557711000000ff00000000666600000000000000 +% 00000033dd99000000000000000000000000000000000000000044eebb1100000000000000000000 +% 2299eeffdd88000011bbffbb1100bbffff44ffffbb00ddffee770000aaff7700aaee88ddddc4ffff +% +% 000066ee330000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000008800000000000000000000990000 +% 00000000000000000033ff5500000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000220000002200002200000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000066ee3300000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 0000000000000000880000000000000000000099000000000000000000000033ff55000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000002200000022 +% 00002200000000000000000000000000000000000000000000000000000000000000000000000000 +% 0000000000000099ee33000000000000000000000000000000000000000000000000000000000000 +% 000000000000000000000000000000000000000000000000000000000000880000ff110000000000 +% 0000000000880000000000000000000088002244000000000000ff00000000990000000000000000 +% 000033ee990000000000000000000000000000000000000000000011aaee55000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% +% 00000088dd2200000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000002255000000000000000077110000 +% 000000000000000022dd880000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 0000000000000000000000000000000000000000000000000088dd22000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000002255000000000000000077110000000000000000000022dd8800000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 000000000000000099ee440000000000000000000000000000000000000000000000000000000000 +% 000000000000000000000000000000000000000000000000000000000000225500ffffff44000000 +% 00000000661100000000000000000066110000000000000088ffff00000077110000000000000000 +% 0044ee990000000000000000000000000000000000000000000000000077ff992200000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% +% 0000000099ee66000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000022110000000000003300000000 +% 0000000000000066ee99000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 000000000000000000000000000000000000000000000000000099ee660000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 000000000000000000221100000000000033000000000000000000000066ee990000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000088eebb33000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000221100000000000000 +% 00000000000000000000000000000000000000000000000000000000003300000000000000000033 +% bbee8800000000000000000000000000000000000000000000000000000033bbffaa550000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% +% 000000000066ee991100000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000001199ee6600000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000066ee9911000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 0000000000000000000000000000000000000000000000000000001199ee66000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 000000000000000000001199ff992200000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 000000000000000000000000000000000000000000000000000000000000000000000000002299ff +% 99110000000000000000000000000000000000000000000000000000000000002288eedd77110000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% +% 00000000000022ccdd44000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 0000000044ddcc220000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 0000000000000000000000000000000000000000000000000000000022ccdd440000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 000000000000000000000000000000000000000000000000000044ddcc2200000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000022aaff99220000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000002299ffaa22 +% 000000000000000000000000000000000000000000000000000000000000000000000066ccff9955 +% 11000000000000000000000000000000000000000000000000000000000000000000000000000000 +% +% 000000000000000088eebb6600000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 000066ccee8800000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000088eebb66000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000066ccee88000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 000000000000000000000000000044aaffcc77220000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000002277ccffaa440000 +% 000000000000000000000000000000000000000000000000000000000000000000000000003399dd +% ffbb8833000000000000000000000000000000000000000000000000000000000000000000000000 +% +% 0000000000000000001188eedd660000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 66ddee88110000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 000000000000000000000000000000000000000000000000000000000000001188eedd6600000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 0000000000000000000000000000000000000000000066ddee881100000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 000000000000000000000000000000001177ccffaa66110000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000001166aaffcc771100000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 3377aaffeeaa66220000000000000000000000000000000000000000000000000000000000000000 +% +% 00000000000000000000001177dddd88330000000000000000000000000000000000000000000000 +% 000000000000000000000000000000000000000000000000000000000000000000000000003388dd +% dd661100000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 0000000000000000000000000000000000000000000000000000000000000000001177dddd883300 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 000000000000000000000000000000000000003388dddd6611000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 000000000000000000000000000000000000002288ddffaa88440000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000004488aaffdd882200000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 000000004488ccffddaa884411000000000000000000000000000000000000000000000000000000 +% +% 000000000000000000000000000066aaeedd88550000000000000000000000000000000000000000 +% 000000000000000000000000000000000000000000000000000000000000000000005588ddee9966 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000066aaeedd +% 88550000000000000000000000000000000000000000000000000000000000000000000000000000 +% 000000000000000000000000000000005588ddee9966000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 000000000000000000000000000000000000000000003388aaeeffbb884400000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 000000000000000000000000000000000000000000004488bbffeeaa883300000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000115588aaddffeebb88663300000000000000000000000000000000000000000000 +% +% 00000000000000000000000000000000005599eeee99773300000000000000000000000000000000 +% 000000000000000000000000000000000000000000000000000000000000337799eeee9955000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000055 +% 99eeee99773300000000000000000000000000000000000000000000000000000000000000000000 +% 000000000000000000000000337799eeee9955000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000003377aaeeffbb8877441100000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 0000000000000000000000000000000011447788bbffeeaa77330000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000011447799ccffffbb9988664422000000000000000000000000000000 +% +% 00000000000000000000000000000000000000005588bbffffbb8855220000000000000000000000 +% 00000000000000000000000000000000000000000000000000225588bbffffbb8855000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00005588bbffffbb8855220000000000000000000000000000000000000000000000000000000000 +% 00000000000000225588bbffffbb8855000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 000000000000000000000000000000000000000000000000000000000000337788bbeeffeebb8877 +% 44220000000000000000000000000000000000000000000000000000000000000000000000000000 +% 0000000000000000000022448888bbeeffeebb887733000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 000000000000000000000000000000000000336688aabbeeffffddbbaa8877443300000000000000 +% +% 000000000000000000000000000000000000000000000000337799ccffffbbbb8888554411000000 +% 00000000000000000000000000000000001144558888bbbbffffcc99773300000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 000000000000337799ccffffbbbb8888554411000000000000000000000000000000000000000011 +% 44558888bbbbffffcc99773300000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 000000000000000000000000000000000000000000000000000000000000000000000011447788bb +% ddffffddbbbb88888844443300000000000000000000000000000000000000000000000000000000 +% 334444888888bbbbddffffddbb887744110000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 000000000000000000000000000000000000000000000000002244668899bbddffffffddbbbbbb88 +% +% 000000000000000000000000000000000000000000000000000000000044448888bbbbffffffffcc +% bbbbbbbbbb99888899bbbbbbbbbbccffffffffbbbb88884444000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 000000000000000000000044448888bbbbffffffffccbbbbbbbbbb99888899bbbbbbbbbbccffffff +% ffbbbb88884444000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 0000444455888899bbbbffffffffffddbbbbbbbbbbbbbbbb88888888bbbbbbbbbbbbbbbbddffffff +% ffeebbbb998888554444000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000022444444888888 +% +% 00000000000000000000000000000000000000000000000000000000000000000000000000444444 +% 44447788888888888888887744444444440000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000444444444477888888888888888877444444444400 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000011444444444444558888888888888888888888885544444444444411 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% +%%EndImage +%%EndPreview +save countdictstack mark newpath /showpage {} def /setpagedevice {pop} def +%%EndProlog +%%Page 1 1 +save +/DotDict 200 dict def +DotDict begin + +/setupLatin1 { +mark +/EncodingVector 256 array def + EncodingVector 0 + +ISOLatin1Encoding 0 255 getinterval putinterval + +EncodingVector + dup 306 /AE + dup 301 /Aacute + dup 302 /Acircumflex + dup 304 /Adieresis + dup 300 /Agrave + dup 305 /Aring + dup 303 /Atilde + dup 307 /Ccedilla + dup 311 /Eacute + dup 312 /Ecircumflex + dup 313 /Edieresis + dup 310 /Egrave + dup 315 /Iacute + dup 316 /Icircumflex + dup 317 /Idieresis + dup 314 /Igrave + dup 334 /Udieresis + dup 335 /Yacute + dup 376 /thorn + dup 337 /germandbls + dup 341 /aacute + dup 342 /acircumflex + dup 344 /adieresis + dup 346 /ae + dup 340 /agrave + dup 345 /aring + dup 347 /ccedilla + dup 351 /eacute + dup 352 /ecircumflex + dup 353 /edieresis + dup 350 /egrave + dup 355 /iacute + dup 356 /icircumflex + dup 357 /idieresis + dup 354 /igrave + dup 360 /dcroat + dup 361 /ntilde + dup 363 /oacute + dup 364 /ocircumflex + dup 366 /odieresis + dup 362 /ograve + dup 365 /otilde + dup 370 /oslash + dup 372 /uacute + dup 373 /ucircumflex + dup 374 /udieresis + dup 371 /ugrave + dup 375 /yacute + dup 377 /ydieresis + +% Set up ISO Latin 1 character encoding +/starnetISO { + dup dup findfont dup length dict begin + { 1 index /FID ne { def }{ pop pop } ifelse + } forall + /Encoding EncodingVector def + currentdict end definefont +} def +/Times-Roman starnetISO def +/Times-Italic starnetISO def +/Times-Bold starnetISO def +/Times-BoldItalic starnetISO def +/Helvetica starnetISO def +/Helvetica-Oblique starnetISO def +/Helvetica-Bold starnetISO def +/Helvetica-BoldOblique starnetISO def +/Courier starnetISO def +/Courier-Oblique starnetISO def +/Courier-Bold starnetISO def +/Courier-BoldOblique starnetISO def +cleartomark +} bind def + +/coord-font-family /Times-Roman def +/default-font-family /Times-Roman def +/coordfont coord-font-family findfont 8 scalefont def + +/InvScaleFactor 1.0 def +/set_scale { + dup 1 exch div /InvScaleFactor exch def + dup scale +} bind def + +% styles +/solid { [] 0 setdash } bind def +/dashed { [9 InvScaleFactor mul dup ] 0 setdash } bind def +/dotted { [1 InvScaleFactor mul 6 InvScaleFactor mul] 0 setdash } bind def +/invis {/fill {newpath} def /stroke {newpath} def /show {pop newpath} def} bind def +/bold { 2 setlinewidth } bind def +/filled { } bind def +/unfilled { } bind def +/rounded { } bind def +/diagonals { } bind def + +% hooks for setting color +/nodecolor { sethsbcolor } bind def +/edgecolor { sethsbcolor } bind def +/graphcolor { sethsbcolor } bind def +/nopcolor {pop pop pop} bind def + +/beginpage { % i j npages + /npages exch def + /j exch def + /i exch def + /str 10 string def + npages 1 gt { + gsave + coordfont setfont + 0 0 moveto + (\() show i str cvs show (,) show j str cvs show (\)) show + grestore + } if +} bind def + +/set_font { + findfont exch + scalefont setfont +} def + +% draw aligned label in bounding box aligned to current point +/alignedtext { % width adj text + /text exch def + /adj exch def + /width exch def + gsave + width 0 gt { + text stringwidth pop adj mul 0 rmoveto + } if + [] 0 setdash + text show + grestore +} def + +/boxprim { % xcorner ycorner xsize ysize + 4 2 roll + moveto + 2 copy + exch 0 rlineto + 0 exch rlineto + pop neg 0 rlineto + closepath +} bind def + +/ellipse_path { + /ry exch def + /rx exch def + /y exch def + /x exch def + matrix currentmatrix + newpath + x y translate + rx ry scale + 0 0 1 0 360 arc + setmatrix +} bind def + +/endpage { showpage } bind def +/showpage { } def + +/layercolorseq + [ % layer color sequence - darkest to lightest + [0 0 0] + [.2 .8 .8] + [.4 .8 .8] + [.6 .8 .8] + [.8 .8 .8] + ] +def + +/layerlen layercolorseq length def + +/setlayer {/maxlayer exch def /curlayer exch def + layercolorseq curlayer 1 sub layerlen mod get + aload pop sethsbcolor + /nodecolor {nopcolor} def + /edgecolor {nopcolor} def + /graphcolor {nopcolor} def +} bind def + +/onlayer { curlayer ne {invis} if } def + +/onlayers { + /myupper exch def + /mylower exch def + curlayer mylower lt + curlayer myupper gt + or + {invis} if +} def + +/curlayer 0 def + +14 default-font-family set_font +1 setmiterlimit +% /arrowlength 10 def +% /arrowwidth 5 def + +% make sure pdfmark is harmless for PS-interpreters other than Distiller +/pdfmark where {pop} {userdict /pdfmark /cleartomark load put} ifelse +% make '<<' and '>>' safe on PS Level 1 devices +/languagelevel where {pop languagelevel}{1} ifelse +2 lt { + userdict (<<) cvn ([) cvn load put + userdict (>>) cvn ([) cvn load put +} if + +gsave +35 35 666 110 boxprim clip newpath +36 36 translate +0 0 1 beginpage +0 0 translate 0 rotate +0.000 0.000 0.000 graphcolor +14.00 /Times-Roman set_font + +% Variable +gsave 10 dict begin +273 90 37 18 ellipse_path +stroke +gsave 10 dict begin +248 85 moveto +(Variable) +[8.88 6.24 4.8 3.84 6.24 6.96 3.84 6.24] +xshow +end grestore +end grestore + +% Constant(1) +gsave 10 dict begin +46 18 46 18 ellipse_path +stroke +gsave 10 dict begin +13 13 moveto +(Constant\(1\)) +[9.36 6.96 6.96 5.28 4.08 6.24 6.96 3.84 4.56 6.96 4.56] +xshow +end grestore +end grestore + +% Variable -> Constant(1) +newpath 242 80 moveto +207 69 150 51 101 36 curveto +98 35 94 34 91 33 curveto +stroke +gsave 10 dict begin +solid +1 setlinewidth +0.000 0.000 0.000 edgecolor +newpath 92 30 moveto +81 30 lineto +90 36 lineto +closepath +fill +0.000 0.000 0.000 edgecolor +newpath 92 30 moveto +81 30 lineto +90 36 lineto +closepath +stroke +end grestore + +% d1 +gsave 10 dict begin +0.000 0.000 1.000 nodecolor +137 18 27 18 ellipse_path +stroke +gsave 10 dict begin +0.000 0.000 0.000 nodecolor +131 13 moveto +(...) +[3.6 3.6 3.6] +xshow +end grestore +end grestore + +% Variable -> d1 +newpath 248 77 moveto +225 65 192 47 167 34 curveto +stroke +gsave 10 dict begin +solid +1 setlinewidth +0.000 0.000 0.000 edgecolor +newpath 168 31 moveto +158 29 lineto +165 37 lineto +closepath +fill +0.000 0.000 0.000 edgecolor +newpath 168 31 moveto +158 29 lineto +165 37 lineto +closepath +stroke +end grestore + +% Constant(n) +gsave 10 dict begin +228 18 46 18 ellipse_path +stroke +gsave 10 dict begin +195 13 moveto +(Constant\(n\)) +[9.36 6.96 6.96 5.28 4.08 6.24 6.96 3.84 4.56 6.96 4.56] +xshow +end grestore +end grestore + +% Variable -> Constant(n) +newpath 262 73 moveto +257 64 250 54 244 44 curveto +stroke +gsave 10 dict begin +solid +1 setlinewidth +0.000 0.000 0.000 edgecolor +newpath 247 43 moveto +239 36 lineto +241 46 lineto +closepath +fill +0.000 0.000 0.000 edgecolor +newpath 247 43 moveto +239 36 lineto +241 46 lineto +closepath +stroke +end grestore + +% d2 +gsave 10 dict begin +0.000 0.000 1.000 nodecolor +319 18 27 18 ellipse_path +stroke +gsave 10 dict begin +0.000 0.000 0.000 nodecolor +313 13 moveto +(...) +[3.6 3.6 3.6] +xshow +end grestore +end grestore + +% Variable -> d2 +newpath 284 73 moveto +290 64 297 53 303 44 curveto +stroke +gsave 10 dict begin +solid +1 setlinewidth +0.000 0.000 0.000 edgecolor +newpath 306 45 moveto +308 35 lineto +300 42 lineto +closepath +fill +0.000 0.000 0.000 edgecolor +newpath 306 45 moveto +308 35 lineto +300 42 lineto +closepath +stroke +end grestore + +% Constant([1,2,3]) +gsave 10 dict begin +425 18 61 18 ellipse_path +stroke +gsave 10 dict begin +377 13 moveto +(Constant\([1,2,3]\)) +[9.36 6.96 6.96 5.28 4.08 6.24 6.96 3.84 4.56 4.56 6.24 3.6 6.96 3.6 6.96 4.56 4.56] +xshow +end grestore +end grestore + +% Variable -> Constant([1,2,3]) +newpath 300 77 moveto +323 66 357 50 384 37 curveto +stroke +gsave 10 dict begin +solid +1 setlinewidth +0.000 0.000 0.000 edgecolor +newpath 385 40 moveto +393 33 lineto +382 34 lineto +closepath +fill +0.000 0.000 0.000 edgecolor +newpath 385 40 moveto +393 33 lineto +382 34 lineto +closepath +stroke +end grestore + +% Constant(instance of A) +gsave 10 dict begin +584 18 80 18 ellipse_path +stroke +gsave 10 dict begin +517 13 moveto +(Constant\(instance of A\)) +[9.36 6.96 6.96 5.28 4.08 6.24 6.96 3.84 4.56 3.84 6.96 5.28 4.08 6.24 6.96 6.24 6.24 3.6 6.96 4.56 3.6 10.08 4.56] +xshow +end grestore +end grestore + +% Variable -> Constant(instance of A) +newpath 307 82 moveto +357 71 454 48 518 33 curveto +stroke +gsave 10 dict begin +solid +1 setlinewidth +0.000 0.000 0.000 edgecolor +newpath 519 36 moveto +528 31 lineto +518 30 lineto +closepath +fill +0.000 0.000 0.000 edgecolor +newpath 519 36 moveto +528 31 lineto +518 30 lineto +closepath +stroke +end grestore +endpage +showpage +grestore +end +restore +%%Trailer +cleartomark countdictstack exch sub { end } repeat restore +%%EOF Added: pypy/extradoc/talk/dls2006/image/lattice1.eps ============================================================================== --- (empty file) +++ pypy/extradoc/talk/dls2006/image/lattice1.eps Wed May 31 14:35:47 2006 @@ -0,0 +1,4371 @@ +%!PS-Adobe-2.0 EPSF-1.2 +%%Title: lattice +%%Creator: dot version 2.2 (Tue Mar 22 18:02:44 UTC 2005) +%%CreationDate: 2006-05-31 14:19 lattice1.ps +%%For: (carlson) Carl Friedrich Bolz +%%Pages: 1 +%%DocumentFonts: +%%BoundingBox: 35 35 466 361 +%%EndComments + +%%BeginProlog +%%BeginPreview: 431 326 8 3586 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000011446688886644 +% 11000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 000000000000000000000000000000000000000000000000000033448888bbccffffeebbaaaabbee +% ffffccbb888844330000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000066bbffccbb8888444400000000000000 +% 0044448888bbccffbb66000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 0000000000000000000000000000000000000000001166ddee881100000000000000000000000000 +% 000000000000001188eedd6611000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 000000000000000000000000000000000000002288eedd6600000000000000000000000000000000 +% 0000000000000000000066ddee882200000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000002299ffbb55000000000000000000000000000000000000 +% 00000000000000000000000055bbff99220000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 0000000000000000000000000000000033eeaa330000000000000000000000000000000000000000 +% 000000000000000000000000000033aaee3300000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000033ee8800000000000000000000000000000000000000000000 +% 0000000000000000000000000000000099ee33000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 000000000000000000000000000033ee660000000000000000000000000000000000000000000000 +% 000000000000000000000000000000000066ee330000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 0000000000000000000000000033ee66000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000066ee3300000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000033ee6600000000000000000000000000000000000000000000000000 +% 0000000000000000000000000000000000000066ee33000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 000000000000000000000033ee660000000000000000000000000000000000000000000000000000 +% 000000000000000000000000000000000000000066ee330000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000009988000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000088990000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 0000000000000000000000ee55000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000055ee0000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 0000000000000000000044ee00000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000ee4400000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 0000000000000000000088990000000000000000000000000000bbffffffffffffff440000000000 +% 00000000000000000000000000000000000000000000aa8800000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000dd66000000000000000000000000000099220000ff000066440000000000 +% 0000000000000000000000000000000000000000000066dd00000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000022ff11000000000000000000000000000000000000ff000000000000000000 +% 0000000000000000000000000000000000000000000011ff22000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000077bb00000000000000000000000000000000000000ff00000011bbffbb1100 +% 44dd99ffdd330000000000000000000000000000000000bb77000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000077bb00000000000000000000000000000000000000ff000000aa660099aa00 +% 00ff440088cc0000000000000000000000000000000000bb77000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000022ff11000000000000000000000000000000000000ff000000ff000011ff00 +% 00ff000011ff0000000000000000000000000000000011ff22000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000dd66000000000000000000000000000000000000ff000000ff220000ff00 +% 00ff000011ee0000000000000000000000000000000066dd00000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 000000000000000000008899000000000000000000000000000000000033ff220000aa9900779900 +% 00ff4400888800000000000000000000000000000000aa8800000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 0000000000000000000044ee00000000000000000000000000000000bbffffff440011bbffbb1100 +% 00ffddff991100000000000000000000000000000000ee4400000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 0000000000000000000000ee55000000000000000000000000000000000000000000000000000000 +% 00ff0000000000000000000000000000000000000055ee0000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 0000000000000000000022c988000000000000000000000000000000000000000000000000000000 +% 11ff1100000000000000000000000000000000000088990000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 000000000000002277ccffd7f0660000000000000000000000000000000000000000000000000000 +% ffffff880000000000000000000000000000000066ee330000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 000000003388ccffaa66220033ee6600000000000000000000000000000000000000000000000000 +% 0000000000000000000000000000000000000066ee33000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 003388ddffaa6611000000000033ee66000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000066ee8500000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000003388 +% ddffaa661100000000000000000033ee660000000000000000000000000000000000000000000000 +% 000000000000000000000000000000000066ee4eddee881100000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000005599eeee99 +% 55000000000000000000000000000033ee8800000000000000000000000000000000000000000000 +% 0000000000000000000000000000000099ee33000066bbee99220000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000005599eeee99550000 +% 0000000000000000000000000000000033f3aa330000000000000000000000000000000000000000 +% 000000000000000000000000000033aaee33000000000044aaff9944000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000005599eeee99550000000000 +% 00000000000000000000000000000011aaf1a7ffbb55000000000000000000000000000000000000 +% 00000000000000000000000055bbff992200000000000000002299ffbb4400000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000115599eedd88440000000000000000 +% 000000000000000000000000000055eebb22002288eedd6600000000000000000000000000000000 +% 0000000000000000000066ddeea0f18800000000000000000000002288eedd660000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 000000000000000000000000000000000000000000001166aaffdd88330000000000000000000000 +% 00000000000000000000000011aaee7700000000001166ddee881100000000000000000000000000 +% 000000000000001188eedd66110033ddcc1100000000000000000000001177dddd88110000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 000000000000000000000000000000000000001166aaffdd88330000000000000000000000000000 +% 000000000000000000000055eebb2200000000000000000066bbffccbb8888444400000000000000 +% 0044448888bbccffbb66000000000011aaee440000000000000000000000000066ddee8822000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 000000000000000000000000000000001166aaffdd88330000000000000000000000000000000000 +% 0000000000000000001188ee770000000000000000000000000033448888bbccffffeebbaaaabbee +% ffffccbb8888443300000000000000000088ff77000000000000000000000000000044bbff992200 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 000000000000000000000000001166aaffdd88330000000000000000000000000000000000000000 +% 000000000000000044ddcc33000000000000000000000000000000000000000000114466c8c86644 +% 11000000000000000000000000000000000044ee991100000000000000000000000000004499ffaa +% 44000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 000000000000000000001166aaffdd88330000000000000000000000000000000000000000000000 +% 0000000000001188ff88000000000000000000000000000000000000000000000000000088880000 +% 0000000000000000000000000000000000000022cccc330000000000000000000000000000002299 +% eebb6600000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 000000000000001166aaffdd88330000000000000000000000000000000000000000000000000000 +% 000000000044ddcc3300000000000000000000000000000000000000000000000000000088880000 +% 00000000000000000000000000000000000000000099ee5500000000000000000000000000000000 +% 1188eedd660000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 000000001166aaffdd88330000000000000000000000000000000000000000000000000000000000 +% 0000000088ff88000000000000000000000000000000000000000000000000000000000088880000 +% 0000000000000000000000000000000000000000000066ff88000000000000000000000000000000 +% 00001166ddee88110000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 001166aaffdd88330000000000000000000000000000000000000000000000000000000000000000 +% 000033ccdd3300000000000000000000000000000000000000000000000000000000000088880000 +% 000000000000000000000000000000000000000000000033ee991100000000000000000000000000 +% 000000000066bbee9922000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000055 +% 99ffdd88330000000000000000000000000000000000000000000000000000000000000000000000 +% 0077ff88110000000000000000000000000000000000000000000000000000000000000088880000 +% 00000000000000000000000000000000000000000000000022cccc11000000000000000000000000 +% 0000000000000044bbff994400000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 0000000000000000000000000000000000000000000000000000000000000000000000005599eedd +% 88330000000000000000000000000000000000000000000000000000000000000000000000000022 +% bbee4400000000000000000000000000000000000000000000000000000000000000000088880000 +% 0000000000000000000000000000000000000000000000000011aaee330000000000000000000000 +% 0000000000000000002299ffbb550000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 0000000000000000000000000000000000000000000000000000000000000000005599eedd883300 +% 000000000000000000000000000000000000000000000000000000000000000000000000000066ee +% aa110000000000000000000000000000000000000000000000000000000000000000000088880000 +% 00000000000000000000000000000000000000000000000000000088ee6600000000000000000000 +% 00000000000000000000002288eedd66000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 0000000000000000000000000000000000000000000000000000000000005599eeee994400000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000011aaee55 +% 00000000000000000000000000000000000000000000000000000000000000000000000088880000 +% 0000000000000000000000000000000000000000000000000000000066ff88000000000000000000 +% 000000000000000000000000001177ddee8811000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 0000000000000000000000000000000000000000000000000000003388eeee995500000000000000 +% 000000000000000000000000000000000000000000000000000000000000000000000055eebb2200 +% 00000000000000000000000000000000000000000000000000000000000000000000000088880000 +% 000000000000000000000000000000000000000000000000000000000033ee991100000000000000 +% 0000000000000000000000000000000066ccee992200000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 0000000000000000000000000000000000000000000000003388ddee995500000000000000000000 +% 0000000000000000000000000000000000000000000000000000000000000000001188ee77000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000088880000 +% 00000000000000000000000000000000000000000000000000000000000011cccc11000000000000 +% 00000000000000000000000000000000000044bbff99440000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 0000000000000000000000000000000000000000002277ccffaa6611000000000000000000000000 +% 000000000000000000000000000000000000000000000000000000000000000044ddcc3300000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000088880000 +% 000000000000000000000000000000000000000000000000000000000000001199ee330000000000 +% 00000000000000000000000000000000000000002299ffbb55000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 0000000000000000000000000000000000001177ccffbb6611000000000000000000000000000000 +% 0000000000000000000000000000000000000000000000000000000000000088ff88000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000088880000 +% 00000000000000000000000000000000000000000000000000000000000000000088ee5500000000 +% 000000000000000000000000000000000000000000002288eedd6611000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 0000000000000000000000000000001166aaffcc7722000000000000000000000000000000000000 +% 000000000000000000000000000000000000000000000000000000000033ccdd3300000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000088880000 +% 0000000000000000000000000000000000000000000000000000000000000000000066ff66000000 +% 0000000000000000000000000000000000000000000000001166ddee881100000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 0000000000000000000000000055aaffdd8822000000000000000000000000000000000000000000 +% 0000000000000000000000000000000000000000000000000000000077ff88110000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000088880000 +% 000000000000000000000000000000000000000000000000000000000000000000000055ee990000 +% 00000000000000000000000000000000000000000000000000000055bbff99220000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 000000000000000000004499eedd8833000000000000000000000000000000000000000000000000 +% 000000000000000000000000000000000000000000000000000022bbee4400000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000088880000 +% 00000000000000000000000000000000000000000000000000000000000000000000000033ee9911 +% 00000000000000000000000000000000000000000000000000000000004499ffbb44000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 000000000000002288ddee9944000000000000000000000000000000000000000000000000000000 +% 0000000000000000000000000000000000000000000000000077eeaa110000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000088880000 +% 0000000000000000000000000000000000000000000000000000000000000000000000000011cccc +% 110000000000000000000000000000000000000000000000000000000000002288eedd6600000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 000000001177ccffaa66000000000000000000000000000000000000000000000000000000000000 +% 000000000000000000000000000000000000000000000011aaee5500000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000088880000 +% 000000000000000000000000000000000000000000000000000000000000000000000000000011bb +% cc33000000000000000000000000000000000000000000000000000000000000001177ddee881100 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 000066aaffcc77110000000000000000000000000000000000000000000000000000000000000000 +% 0000000000000000000000000000000000000000000055eebb220000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000088880000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 99ee3300000000000000000000000000000000000000000000000000000000000000000066bbff99 +% 22000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000055 +% 99eedd88220000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000001199ee7700000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000088880000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 0077ff66000000000000000000000000000000000000000000000000000000000000000000004499 +% ffbb4400000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 0000000000000000000000000000000000000000000000000000000000000000000000003388ddee +% 99440000000000000000000000000000000000000000000000000000000000000000000000000000 +% 0000000000000000000000000000000000000044ddcc220000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000088880000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 000066ff660000000000000000000000000000000000000000000000000000000000000000000000 +% 2288eedd661100000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 0000000000000000000000000000000000000000000000000000000000000000001177ccffaa6600 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000088ff8800000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000088880000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000033ee9900000000000000000000000000000000000000000000000000000000000000000000 +% 00001166ddee88220000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 0000000000000000000000000000000000000000000000000000000000000055aaffcc6611000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 0000000000000000000000000000000033cccc330000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000088880000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 0000000033ee99000000000000000000000000000000000000000000000000000000000000000000 +% 000000000055bbff9933000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 000000000000000000000000000000000000000000000000000000003388eeee8822000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000088ff8811000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000088880000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 000000000022ccbb1100000000000000000000000000000000000000000000000000000000000000 +% 000000000000003399ffbb6600000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 000000000000000000000000000000000000000000000000001166ccffaa55000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 0000000000000000000000000033ccdd440000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000088880000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000011cccc11000000000000000000000000000000000000000000000000000000000000 +% 0000000000000000001188eedd881100000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000005599ffcc77110000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000088ff8811000000000000000000000000000000000000000000000000 +% 000000000000000000000000000000000000000000000000000000000000000000338888c8c88888 +% 88220000000000000000000000000000000000000000000000000000000000000000000000000000 +% 0000000000000011aacc330000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000066ccff99220000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000002288ddee99330000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 0000000000000000000022ccdd440000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000077fdffffffffff +% ff660000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000099ee3300000033220000000000000000000000000000000000000000000000 +% 00000000000000000000000000004499ffbb55000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000001166bbffaa660000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000077ee9911000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000022ffffffffffff +% f8110000000000000000000000000000000000000000000000000000000000000000000000000000 +% 0000000000000000000099ee440066ffeb1100000000000000000000000000000000000000000000 +% 000000000000000000000000000000002288eedd7711000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 0000000000000000000000000000004499eedd772200000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 0022220000000022bbee550000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000e9ffffffffff +% a7000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 000000000000000000000066ff8ffffffb9000000000000000000000000000000000000000000000 +% 0000000000000000000000000000000000000066ccee992200000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 0000000000000000000000001177ddee994400000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 11f6f611000077eeaa11000000000000000000000000000000000000000000000000000000000000 +% 0000000000000000000000000000000000000000000000000000000000000000000090ffffffffff +% 33000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000085fffffffff822000000000000000000000000000000000000000000 +% 0000000000000000000000000000000000000000004499ffbb550000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 000000000000000000004499ffcc6611000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% b6fafab622bbee550000000000000000000000000000000000000000000000000000000000000000 +% 0000000000000000000000000000000000000000000000000000000000000000000044faffffffdd +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 000000000000000000000066fffffffffffba0000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000002288eedd77110000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 000000000000001177ddee9933000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000055 +% fbfffffcf4aa11000000000000000000000000000000000000000000000000000000000000000000 +% 0000000000000000000000000000000000000000000000000000000000000000000000f6fffffb66 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 0000000000000000000055ffffffffffffffff330000000000000000000000000000000000000000 +% 000000000000000000000000000000000000000000000000000066ccff9933000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000004499ffcc66110000000000000000000000000000000000000000000000000000000000 +% 000000000000000000000000000000000000000000000000000000000000000000000000000011f6 +% fffffffff91100000000000000000000000000000000000000000000000000000000000000000000 +% 0000000000000000000000000000000000000000000000000000000000000000000000a7fffff811 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 0000000000000000000022e9ffffffffffffffc40000000000000000000000000000000000000000 +% 000000000000000000000000000000000000000000000000000000003399ffcc6600000000000022 +% 55000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00001177ddee99330000000000000000000000000000000000000000000000000000000000000000 +% 0000000000000000000000000000000000000000000000000000000000000000000000000000b6fa +% fffffffffab600000000000000000000000000000000000000000000000000000000000000000000 +% 000000000000000000000000000000000000000000000000000000000000000000000066f9ffa700 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000044a7fffbfffffffb4400000000000000000000000000000000000000 +% 0000000000000000000000000000000000000000000000000000000000001188ddee8822000000eb +% ff800000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 4499ffcc661100000000000000000000000000000000000000000000000000000000000000000000 +% 0000000000000000000000000000000000000000000000000000000000000000000000000055fbff +% ffffffffffff55000000000000000000000000000000000000000000000000000000000000000000 +% 000000000000000000000000000000000000000000000000000000000000000000000011ffff3300 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000001177e9ffffffe600000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000055bbffaa4466fb +% fffca000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000011 +% 446688886644110000000000000000000000000000000000000000000000005522000000000066dd +% ee993300000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000033444444447788888888888888887744444444330000000000000000000000000011f6ffff +% fffffff9ffc922000000000000000000000000000000000000000000000000000000003388888888 +% 888888888888888888888888888888888888888888888888888888888888888888888888e6f08888 +% 88888888888888888888888888888888888888888888888888888888888888888888888888883300 +% 0000000000000000000000000000003388a8d6ffffb8888888888888888888888888888888888888 +% 88888888888888888888888888888888888888888888888888888888888833000000002299eefdff +% fffff9bb110000338888888888888888888888888888888888888888888888888888888888888888 +% 88888888888888888888888888888888888888888888888888888888888833 +% 000000000000000000000000000000000000000000000000000000000000000033448888bbccffff +% eebbaaaabbeeffffccbb888844330000000000000000000000000000000080ffeb00000066dddd66 +% 110000000000000000000000000000000000000000000000000000000000000000000033447788aa +% bbeeffffffccbbbbbbbbbb99888899bbbbbbbbbbccffffffeebbaa887744330000000000b6fbffff +% faf6a7661100000000000000000000000000000000000000000000000000000000000088bb888888 +% 88888888888888888888888888888888888888888888888888888888888888888888888898988888 +% 88888888888888888888888888888888888888888888888888888888888888888888888888bb8800 +% 00000000000000000000000000000088bb888890c090888888888888888888888888888888888888 +% 8888888888888888888888888888888888888888888888888888888888bb8800000000000070fdff +% fffffffcd7110088bb88888888888888888888888888888888888888888888888888888888888888 +% 8888888888888888888888888888888888888888888888888888888888bb88 +% 00000000000000000000000000000000000000000000000000000000000066bbffccbb8888444400 +% 0000000000000044448888bbccffbb6600000000000000000000000000a0fcfffb6666dddd660000 +% 000000000000000000000000000000000000000000000000000000000000115588bbffffddbb9988 +% 66442200000000000000000000000000000000000000002244668899bbddffffbb885560ffffe990 +% 44000000000000000000000000000000000000000000000000000000000000000000008888000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000888800 +% 00000000000000000000000000000088880000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000008888000000000000ebffff +% fffffffffaeb33888800000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000008888 +% 0000000000000000000000000000000000000000000000000000001166ddee881100000000000000 +% 000000000000000000000000001188eedd6611000000000000000011bbf9fffffffddd6600000000 +% 00000000000000000000000000000000000000000000000000002277aaddffdd9977440000000000 +% 00000000000000000000000000000000000000000000000000000000000000447799ddffedb67722 +% 00000000000000000000000000000000000000000000000000000000000000000000008888000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000888800 +% 00000000000000000000000000000088880000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000008888000000000066ffffff +% fffffffffffff5a08800000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000008888 +% 000000000000000000000000000000000000000000000000002288eedd6600000000000000000000 +% 0000000000000000000000000000000066ddee8822000000000011d7fcfffffffffd660000000000 +% 00000000000000000000000000000000000000000000002277ccffcc885511000000000000000000 +% 0000000000000000000000000000000000000000000000000000000000000000000000115588ccff +% cc772200000000000000000000000000000000000000000000000000000000000000008888000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000888800 +% 00000000000000000000000000000088880000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000008888000000000022a7cdcd +% f6fffffffbf2ffffa800000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000008888 +% 00000000000000000000000000000000000000000000002299ffbb55000000000000000000000000 +% 00000000000000000000000000000000000055bbff9922000033ebfaffffffffffffeb0000000000 +% 00000000000000000000000000000000000000001177ccffcc772200000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000022 +% 77ccffcc771100000000000000000000000000000000000000000000000000000000008888000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000888800 +% 00000000000000000000000000000088880000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000008888000000000000000000 +% 00000044445588c89000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000008888 +% 0000000000000000000000000000000000000000000033eeaa330000000000000000000000000000 +% 000000000000000000000000000000000000000033aaee3333f5ffffffffffffffffff6600000000 +% 0000000000000000000000000000000000002288eecc772200000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00002277ccee88220000000000000000000000000000000000000000000000000000008888000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000888800 +% 00000000000000000000000000000088880000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000008888000000000000000000 +% 00000000000000888800000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000008888 +% 00000000000000000000000000000000000000000033ee8800000000000000000000000000000000 +% 0000000000000000000000000000000000000000000099f3ffffedfbfffffff5cdcda02200000000 +% 000000000000000000000000000000002299ffbb4400000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 000000000044bbff9922000000000000000000000000000000000000000000000000008888000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000888800 +% 00000000000000000000000000000088880000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000008888000000000000000000 +% 00000000000000888800000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000008888 +% 000000000000000000000000000000000000000033ee660000000000000000000000000000000000 +% 000000000000000000000000000000000000000000000070f8a05544440000000000000000000000 +% 00000000000000000000000000001199ffbb44000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 0000000000000044bbff991100000000000000000000000000000000000000000000008888000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000888800 +% 00000000000000000000000000000088880000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000008888000000000000000000 +% 00000000000000888800000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000008888 +% 0000000000000000000000000000000000000033ee66000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000066ee3300000000000000000000000000 +% 0000000000000000000000000033ddcc330000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000033ccdd33000000000000000000000000000000000000000000008888000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000888800 +% 00000000000000000000000000000088880000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000008888000000000000000000 +% 00000000000000888800000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000008888 +% 00000000000000000000000000000000000033ee6600000000000000000000000000000000000000 +% 0000000000000000000000000000000000000000000000000066ee33000000000000000000000000 +% 00000000000000000000000077ff8800000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 000000000000000000000088ff770000000000000000000000000000000000000000008888000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000888800 +% 00000000000000000000000000000088880000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000008888000000000000000000 +% 00000000000000888800000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000008888 +% 000000000000000000000000000000000033ee660000000000000000000000000000000000000000 +% 000000000000000000000000000000000000000000000000000066ee330000000000000000000000 +% 0000000000000000000000aaee440000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000044eeaa00000000000000000000000000000000000000008888000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000888800 +% 00000000000000000000000000000088880000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000008888000000000000000000 +% 00000000000000888800000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000008888 +% 00000000000000000000000000000000009988000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000088990000000000000000000000 +% 0000000000000000000099cc11000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 0000000000000000000000000011cc99000000000000000000000000000000000000008888000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000888800 +% 00000000000000000000000000000088880000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000008888000000000000000000 +% 00000000000000888800000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000008888 +% 0000000000000000000000000000000000ee55000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000055ee0000000000000000000000 +% 00000000000000000066ee3300000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 000000000000000000000000000033ee660000000000000000000000000000000000008888000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000888800 +% 00000000000000000000000000000088880000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000008888000000000000000000 +% 00000000000000888800000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000008888 +% 0000000000000000000000000000000044ee00000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000ee4400000000000000000000 +% 000000000000000033ee550000000000000000000000000000000000000000000000000000116600 +% 00116600000000000000001166000000000011660000000000000000000000000000000000000000 +% 00000000000000000000000000000066ee3300000000000000000000000000000000008888000000 +% 00000000000000660000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000660000000000000000000000888800 +% 00000000000000000000000000000088880000000000000000000066000000116600000000000000 +% 00000000000000000000000000000000660000000000000000000000008888000000000000000000 +% 00000000000000888800000000000000000000660000000000000000000000000000220000000000 +% 00000000000000000000000000000000000066000000000000000000008888 +% 0000000000000000000000000000000088990000000000000000000000000000000000bbffffff88 +% 00000000000000000000000000000000000000000000000000000000aa8800000000000000000000 +% 0000000000000000aa9900000000000000000000bbffee11000088ffffff0000000000000033ff00 +% 0033ff000000000000000055ff000000000033ff00000000000000000033ddffcc88440000000000 +% 0000000000000000000000000000000099aa00000000000000000000000000000000008888000000 +% 00000000003300ff00330000bb000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000003300ff0033000000000000000000888800 +% 000000000000000000000000000000888800000000000000003300ff00330033ff000000bb000000 +% 00000000000000000000000000003300ff0033000000000000000000008888000000000000000000 +% 00000000000000888800000000000000003300ff003300bbffffffee992200bbffff224444882200 +% 00001199eeffdd8877000000000000003300ff003300000000000000008888 +% 00000000000000000000000000000000dd6600000000000000000000000000000000000033ff2200 +% 0000000000000000660000000000000000000000000000000000000066dd00000000000000000000 +% 0000000000000000ee440000000000000000000033ffddcc11000033ff330000000000000000ff00 +% 0000ff000000000000000000ff000000000000ff000000000000000000ee550033cc770066000000 +% 0000000000000000000000000000000044ee00000000000000000000000000000000008888000000 +% 0000000000bb33ff44cc000000000000000000000000000000000000660000000000000000000000 +% 0000000000000000000000000000000000000000000000bb33ff44cc000000000000000000888800 +% 00000000000000000000000000000088880000000000000000bb33ff44cc0000ff00000000000000 +% 0000000000660000000000000000bb33ff44cc000000000000000000008888000000000000000000 +% 0000000000000088880000000000000000bb33ff44cc000033ff001188bb000033ff00000011dd00 +% 0011cc88110033aa8800000000000000bb33ff44cc00000000000000008888 +% 00000000000000000000000000000022ff1100000000000000000000000000000000000000ff0000 +% 0000000000000000dd0000000000000000000000000000000000000011ff22000000000000000000 +% 0000000000000033ff000000000000000000000000ff33ee99000000ff000000000000000000ff00 +% 0000ff000000000000000000ff000000000000ff000000000000000000ee110000117700dd000000 +% 0000000000000000000000000000000000ff33000000000000000000000000000000008888000000 +% 00000000000088ff6600000044000000000000000000000000000000dd0000000000000000000000 +% 00000000000000000000000000000000000000000000000088ff6600000000000000000000888800 +% 000000000000000000000000000000888800000000000000000088ff66000000ff00000044000000 +% 0000000000dd00000000000000000088ff6600000000000000000000008888000000000000000000 +% 00000000000000888800000000000000000088ff6600000000ff000000ff000000ff00000011ff00 +% 009988000000000099000000000000000088ff660000000000000000008888 +% 00000000000000000000000000000077bb0000000000000000000000000000000000000000ff0000 +% 44cc99ddff880088ffff88000000000000000000000000000000000000bb77000000000000000000 +% 0000000000000077aa000000000000000000000000ff0033ee880000ff00bbff0044ffff0000ff00 +% 0000ff000088eeff88000000ff99ffdd330000ff00000066ddffbb110066cc4400000088ffff8855 +% dd44aa9900000000000000000000000000bb77000000000000000000000000000000008888000000 +% 0000000000dd33bb22dd0044ff000044cc99ddff88000088ffff6688ffff880088eeff880044cc99 +% ddff88001188eeffcc33000066ddffbb110088ffff6600dd33bb22dd000000000000000000888800 +% 00000000000000000000000000000088880000000000000000dd33bb22dd0000ff000044ff000000 +% 88ffff6688ffff880088ffff6600dd33bb22dd000000000000000000008888000000000000000000 +% 0000000000000088880000000000000000dd33bb22dd000000ff001188bb000000ff000022998800 +% 00ee220000000000000088ffff660000dd33bb22dd00000000000000008888 +% 00000000000000000000000000000077bb0000000000000000000000000000000000000000ff0000 +% 00ff660033ff0000ff0000000000000000000000000000000000000000bb77000000000000000000 +% 0000000000000077aa000000000000000000000000ff000055ff6600ff0011ff000011ff0000ff00 +% 0000ff0000aa0033ff000000ff440099bb0000ff000044ffffffff8800001188aa440000ff000000 +% ff00000000000000000000000000000000bb77000000000000000000000000000000008888000000 +% 00000000000000ee00000000ff000000ff660033ff0000ff22114400ff000000aa0033ff0000ff66 +% 0033ff009999110088440044ffffffff8800ff221144000000ee0000000000000000000000888800 +% 000000000000000000000000000000888800000000000000000000ee00000000ff000000ff000000 +% ff22114400ff000000ff221144000000ee0000000000000000000000008888000000000000000000 +% 00000000000000888800000000000000000000ee0000000000ffffffaa11000000ffffffffaa1100 +% 00ff0000000000000000ff22114400000000ee000000000000000000008888 +% 00000000000000000000000000000022ff1100000000000000000000000000000000000000ff0000 +% 00ff000000ff0000ff0000000000000000000000000000000000000011ff22000000000000000000 +% 0000000000000033ff000000000000000000000000ff00000066ee33ff0000ff000000ff0000ff00 +% 0000ff0000001166ff000000ff000011ff0000ff00008877000000000000000011996600ff000000 +% ff00000000000000000000000000000000ff33000000000000000000000000000000008888000000 +% 000000000000002200000000ff000000ff000000ff00005577110000ff000000001166ff0000ff00 +% 0000ff00ee1100000000008877000000000055771100000000220000000000000000000000888800 +% 0000000000000000000000000000008888000000000000000000002200000000ff000000ff000000 +% 5577110000ff00000055771100000000220000000000000000000000008888000000000000000000 +% 00000000000000888800000000000000000000220000000000ff00000000000000ff00003399bb00 +% 00ee2200000000000000557711000000000022000000000000000000008888 +% 00000000000000000000000000000000dd6600000000000000000000000000000000000000ff0000 +% 00ff000000ff0000ff0000000000000000000000000000000000000066dd00000000000000000000 +% 0000000000000000ee440000000000000000000000ff0000000088eeff0000ff000000ff0000ff00 +% 0000ff0000333300ff000000ff000000ee0000ff0000aa9900000022443300000000ff00ff000000 +% ff00000000000000000000000000000044ee00000000000000000000000000000000008888000000 +% 000000000000000000000000ff000000ff000000ff00001111776600ff000000333300ff0000ff00 +% 0000ff00ff220000001100aa99000000220011117766000000000000000000000000000000888800 +% 0000000000000000000000000000008888000000000000000000000000000000ff000000ff000000 +% 1111776600ff00000011117766000000000000000000000000000000008888000000000000000000 +% 00000000000000888800000000000000000000000000000000ff00000000000000ff00000000ff00 +% 00998800000000000000111177660000000000000000000000000000008888 +% 00000000000000000000000000000000889900000000000000000000000000000000000022ff2200 +% 11ff110011ff1100ff11000000000000000000000000000000000000aa8800000000000000000000 +% 0000000000000000aa990000000000000000000011ff440000000099ff0000ff330055ff0011ff22 +% 0011ff2200ee3344ff110000ff220088880011ff220066ff5500446644ee66000077dd00ff110011 +% ff22000000000000000000000000000099aa00000000000000000000000000000000008888000000 +% 000000000000000000000011ff220011ff110011ff1100990033ff00ff110000ee3344ff1111ff11 +% 0011ff11aacc220044660066ff5500446600990033ff000000000000000000000000000000888800 +% 0000000000000000000000000000008888000000000000000000000000000011ff220011ff220000 +% 990033ff00ff110000990033ff000000000000000000000000000000008888000000000000000000 +% 00000000000000888800000000000000000000000000000033ff11000000000033ff11002288bb00 +% 0022ee88220011557700990033ff0000000000000000000000000000008888 +% 0000000000000000000000000000000044ee0000000000000000000000000000000000bbffffff88 +% bbffff44ffffbb00aaff770000000000000000000000000000000000ee4400000000000000000000 +% 000000000000000033ee55000000000000000000bbffff880000000099000088ffdd77cc44bbffff +% 88bbffff88aaee88dddd220099ffff880000bbffff880088ffee880011cc55ddffaa3300aaff77ff +% ffff8800000000000000000000000066ee3300000000000000000000000000000000008888000000 +% 0000000000000000000000bbffff88bbffff44ffffbb00ddffee7700aaff7700aaee88ddddc4ffff +% 44ffffbb11aaffee8800000088ffee880000ddffee77000000000000000000000000000000888800 +% 00000000000000000000000000000088880000000000000000000000000000bbffff88bbffff8800 +% ddffee7700aaff7700ddffee77000000000000000000000000000000008888000000000000000000 +% 0000000000000088880000000000000000000000000000bbffffff44000000bbffffffffffaa1100 +% 00002299eeffdd880000ddffee770000000000000000000000000000008888 +% 0000000000000000000000000000000000ee55000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000055ee0000000000000000000000 +% 00000000000000000066ee3300000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 000000000000000000000000000033ee660000000000000000000000000000000000008888000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000888800 +% 00000000000000000000000000000088880000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000008888000000000000000000 +% 00000000000000888800000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000008888 +% 00000000000000000000000000000000009988000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000088990000000000000000000000 +% 0000000000000000000099cc11000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 0000000000000000000000000011cc99000000000000000000000000000000000000008888000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000888800 +% 00000000000000000000000000000088880000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000008888000000000000000000 +% 00000000000000888800000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000008888 +% 000000000000000000000000000000000033ee660000000000000000000000000000000000000000 +% 000000000000000000000000000000000000000000000000000066ee330000000000000000000000 +% 0000000000000000000000aaee440000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000044eeaa00000000000000000000000000000000000000008888000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000888800 +% 00000000000000000000000000000088880000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000008888000000000000000000 +% 00000000000000888800000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000008888 +% 00000000000000000000000000000000000033ee6600000000000000000000000000000000000000 +% 0000000000000000000000000000000000000000000000000066ee33000000000000000000000000 +% 00000000000000000000000077ff8800000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 000000000000000000000088ff770000000000000000000000000000000000000000008888000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000888800 +% 00000000000000000000000000000088880000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000008888000000000000000000 +% 00000000000000888800000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000008888 +% 0000000000000000000000000000000000000033ee66000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000066ee3300000000000000000000000000 +% 0000000000000000000000000033ddcc330000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000033ccdd33000000000000000000000000000000000000000000008888000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000888800 +% 00000000000000000000000000000088880000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000008888000000000000000000 +% 00000000000000888800000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000008888 +% 000000000000000000000000000000000000000033ee660000000000000000000000000000000000 +% 000000000000000000000000000000000000000000000066ee330000000000000000000000000000 +% 00000000000000000000000000001199ffbb44000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 0000000000000044bbff991100000000000000000000000000000000000000000000008888000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000888800 +% 00000000000000000000000000000088880000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000008888000000000000000000 +% 00000000000000888800000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000008888 +% 00000000000000000000000000000000000000000033ee8800000000000000000000000000000000 +% 0000000000000000000000000000000000000000000099ee33000000000000000000000000000000 +% 000000000000000000000000000000002299ffbb4400000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 000000000044bbff9922000000000000000000000000000000000000000000000000008888000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000888800 +% 00000000000000000000000000000088880000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000008888000000000000000000 +% 00000000000000888800000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000008888 +% 0000000000000000000000000000000000000000000033eeaa330000000000000000000000000000 +% 000000000000000000000000000000000000000033aaee3300000000000000000000000000000000 +% 0000000000000000000000000000000000002288eecc772200000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00002277ccee88220000000000000000000000000000000000000000000000000000008888000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000888800 +% 00000000000000000000000000000088880000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000008888000000000000000000 +% 00000000000000888800000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000008888 +% 00000000000000000000000000000000000000000000002299ffbb55000000000000000000000000 +% 00000000000000000000000000000000000055bbff99220000000000000000000000000000000000 +% 00000000000000000000000000000000000000001177ccffcc772200000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000022 +% 77ccffe1771100000000000000000000000000000000000000000000000000000000008888000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000888800 +% 00000000000000000000000000000088880000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000008888000000000000000000 +% 00000000000000888800000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000008888 +% 000000000000000000000000000000000000000000000000002288eedd6600000000000000000000 +% 0000000000000000000000000000000066ddee882200000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000002277ccffcc885511000000000000000000 +% 0000000000000000000000000000000000000000000000000000000000000000000000115588ccff +% cc773fdddd8811000000000000000000000000000000000000000000000000000000008888000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000888800 +% 00000000000000000000000000000088880000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000008888000000000000000000 +% 00000000000000888800000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000008888 +% 0000000000000000000000000000000000000000000000000000001166ddee881100000000000000 +% 000000000000000000000000001188eedd6611000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000002277aaddffdd9977440000000000 +% 00000000000000000000000000000000000000000000000000000000000000447799ddffddaa7722 +% 0000000066ddee881100000000000000000000000000000000000000000000000000008888000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000888800 +% 00000000000000000000000000000088880000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000008888000000000000000000 +% 00000000000000888800000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000008888 +% 00000000000000000000000000000000000000000000000000000000000066bbffccbb8888444400 +% 0000000000000044448888bbccffbb66000000000000000000000000000000000000000000000000 +% 000000000000000000000000000000000000000000000000000000000000115588bbffffddbb9988 +% 66442200000000000000000000000000000000000000002244668899bbddffffbb88551100000000 +% 00000000000055bbee88220000000000000000000000000000000000000000000000008888000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000888800 +% 00000000000000000000000000000088880000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000008888000000000000000000 +% 00000000000000888800000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000008888 +% 000000000000000000000000000000000000000000000000000000000000000033448888bbccffff +% eebbaaaabbeeffffccbb888844330000000000000000000000000000000000000000000000000000 +% 000000000000000000000000000000000000000000000000000000000000000000000033447788aa +% bbeeffffffccbbbbbbbbbb99888899bbbbbbbbbbd3ffffffeebbaa88774433000000000000000000 +% 000000000000000044bbff99220000000000000000000000000000000000000000000088bb888888 +% 88888888888888888888888888888888888888888888888888888888888888888888888888888888 +% 88888888888888888888a08888888888888888888888888888888888888888888888888888bb8800 +% 00000000000000000000000000000088bb8888888888888888888888888888888888988888888888 +% 8888888888888888888888888888888888888888888888888888888888bb88000000000000000000 +% 0000000000000088bb88b08888888888888888888888888888888888888888988888888888888888 +% 8888888888888888888888888888888888888888888888888888888888bb88 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000011 +% 446688c8b84411000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 000000334444444477888888888888888877449bda44330000000000000000000000000000000000 +% 000000000000000000004499ff992200000000000000000000000000000000000000003388888888 +% 888888888888888888888888888888888888888888888888888888888888888888888888c8c88888 +% 888888888888888888a8f8a088888888888888888888888888888888888888888888888888883300 +% 00000000000000000000000000000033888888888888888888888888888888888888f0b888888888 +% 88888888888888888888888888888888888888888888888888888888888833000000000000000000 +% 000000000000003398e0f89888888888888888888888888888888888888888f0b888888888888888 +% 88888888888888888888888888888888888888888888888888888888888833 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000088bb0000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 0000000000000000000000000000000000000022ff22000000000000000000000000000000000000 +% 0000000000000000000000002299ffbb440000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000088880000 +% 0000000000000000000088dd11000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000066ee0000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 0000000000000077eeaa110000000000000000000000000000000000000066ee0000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000077bb0000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 0000000000000000000000000000000000000000aa88000000000000000000000000000000000000 +% 00000000000000000000000000002299ffbb44000000000000000000000000000000000000000000 +% 000000000000000000000000000000000000000000000000000000000000000000000000aa880000 +% 0000000000000000000000bbbb000000000000000000000000000000000000000000000000000000 +% 000000000000000000000000000000000000000000000000000000000000000000cc880000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 000000000033ccdd55000000000000000000000000000000000000000000cc880000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000044bb0000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 000000000000000000000000000000000000000066dd000000000000000000000000000000000000 +% 000000000000000000000000000000001188eecc6600000000000000000000000000000000000000 +% 000000000000000000000000000000000000000000000000000000000000000000000000bb880000 +% 000000000000000000000011dd880000000000000000000000000000000000000000000000000000 +% 000000000000000000000000000000000000000000000000000000000000000044ee110000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 0000000088ff881100000000000000000000000000000000000000000044ee110000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000044dd0000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 000000000000000000000000000000000000000011ff330000000000000000000000000000000000 +% 0000000000000000000000000000000000001188eedd660000000000000000000000000000000000 +% 000000000000000000000000000000000000000000000000000000000000000000000000bb880000 +% 00000000000000000000000033ee6600000000000000000000000000000000000000000000000000 +% 0000000000000000000000000000000000000000000000000000000000000000bb88000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 000044ccdd440000000000000000000000000000000000000000000000bb88000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000044ff0000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 000000000000000000000000000000000000000000aa880000000000000000000000000000000000 +% 00000000000000000000000000000000000000001166dddd66110000000000000000000000000000 +% 000000000000000000000000000000000000000000000000000000000000000000000000bb880000 +% 0000000000000000000000000066ee33000000000000000000000000000000000000000000000000 +% 0000000000000000000000000000000000000000000000000000000000000044ff22000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 1188ff8811000000000000000000000000000000000000000000000044ff11000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000022ff0000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000055dd0000000000000000000000000000000000 +% 000000000000000000000000000000000000000000000066ddee8811000000000000000000000000 +% 000000000000000000000000000000000000000000000000000000000000000000000000bb880000 +% 000000000000000000000000000088dd110000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000999900000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000044 +% ddcc3300000000000000000000000000000000000000000000000000aa9900000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000ff0000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000ee4400000000000000000000000000000000 +% 0000000000000000000000000000000000000000000000000066bbee992200000000000000000000 +% 000000000000000000000000000000000000000000000000000000000000000000000000bb550000 +% 000000000000000000000000000000bbbb0000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000022ff2200000000000000 +% 0000000000000000000000000000000000000000000000000000000000000000000000000011aaee +% 88000000000000000000000000000000000000000000000000000022ff2200000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000ff4400000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000999900000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000044bbff99220000000000000000 +% 000000000000000000000000000000000000000000000000000000000000000000000000bb440000 +% 00000000000000000000000000000011dd8800000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000099990000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000055eebb22 +% 00000000000000000000000000000000000000000000000000000099990000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000ff4400000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 0000000000000000000000000000000000000000000055ee00000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000002299ffbb44000000000000 +% 000000000000000000000000000000000000000000000000000000000000000000000000bb440000 +% 0000000000000000000000000000000033ee66000000000000000000000000000000000000000000 +% 000000000000000000000000000000000000000000000000000000000022ff440000000000000000 +% 0000000000000000000000000000000000000000000000000000000000000000000011aaee770000 +% 000000000000000000000000000000000000000000000000000022ff330000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000bb4400000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 0000000000000000000000000000000000000000000000dd55000000000000000000000000000000 +% 000000000000000000000000000000000000000000000000000000000000002299eebb6600000000 +% 000000000000000000000000000000000000000000000000000000000000000000000000bb440000 +% 000000000000000000000000000000000066ee330000000000000000000000000000000000000000 +% 000000000000000000000000000000000000000000000000000000000088bb000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000055eebb22000000 +% 000000000000000000000000000000000000000000000000000088bb000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000bb5500000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000008899000000000000000000000000000000 +% 0000000000000000000000000000000000000000000000000000000000000000001188eedd660000 +% 000000000000000000000000000000000000000000000000000000000000000000000000bb440000 +% 00000000000000000000000000000000000088dd1100000000000000000000000000000000000000 +% 0000000000000000000000000000000000000000000000000000000011ee44000000000000000000 +% 000000000000000000000000000000000000000000000000000000000000001188ee770000000000 +% 0000000000000000000000000000000000000000000000000011ee44000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000bb8800000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 000000000000000000000000000000000000000000000033ff110000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000001166dddd88 +% 110000000000000000000000000000000000000000000000000000000000000000000000ee440000 +% 00000000000000000000000000000000000000bbbb00000000000000000000000000000000000000 +% 0000000000000000000000000000000000000000000000000000000088cc00000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000044ddcc22000000000000 +% 0000000000000000000000000000000000000000000000000088bb00000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000bb8800000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 000000000000000000000000000000000000000000000000dd660000000000000000000000000000 +% 000000000000000000000000000000000000000000000000000000000000000000000000000066dd +% ee8822000000000000000000000000000000000000000000000000000000000000000000ff440000 +% 0000000000000000000000000000000000000011dd88000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000011ee6600000000000000000000 +% 000000000000000000000000000000000000000000000000000000001188ff880000000000000000 +% 00000000000000000000000000000000000000000000000011ee5500000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000bb8800000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000077cc0000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 44bbff992200000000000000000000000000000000000000000000000000000000000000ff440000 +% 000000000000000000000000000000000000000033ff440000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000088dd0000000000000000000000 +% 00000000000000000000000000000000000000000000000000000044ddcc33000000000000000000 +% 00000000000000000000000000000000000000000000000077dd0000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000bb8800000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000022ff2200000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00004499ff99440000000000000000000000000000000000000000000000000000000000ff440000 +% 00000000000000000000000000000000000000000077ee1100000000000000000000000000000000 +% 000000000000000000000000000000000000000000000000000011ee660000000000000000000000 +% 000000000000000000000000000000000000000000000000001188ff880000000000000000000000 +% 000000000000000000000000000000000000000000000000dd660000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000bb8800000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000aa8800000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 000000002299ffbb44000000000000000000000000000000000000000000000000000000ff440000 +% 00000000000000000000000000000000000000000000bbaa00000000000000000000000000000000 +% 000000000000000000000000000000000000000000000000000088dd000000000000000000000000 +% 00000000000000000000000000000000000000000000000044ddcc33000000000000000000000000 +% 000000000000000000000000000000000000000000000066dd000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000bb8800000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 0000000000000000000000000000000000000000000000000055ee00000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 0000000000002288eedd6600000000000000000000000000000000000000000000000000ff110000 +% 0000000000000000000000000000000000000000000011ee77000000000000000000000000000000 +% 0000000000000000000000000000000000000000000000000011ee66000000000000000000000000 +% 000000000000000000000000000000000000000000001188ff880000000000000000000000000000 +% 0000000000000000000000000000000000000000000000dd66000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000bb8800000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 0000000000000000000000000000000000000000000000000000dd66000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000001188dddd881100000000000000000000000000000000000000000000ff000000 +% 000000000000000000000000000000000000000000000055ff330000000000000000000000000000 +% 0000000000000000000000000000000000000000000000000088dd00000000000000000000000000 +% 00000000000000000000000000000000000000000033cccc33000000000000000000000000000000 +% 0000000000000000000000000000000000000000000066dd00000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000998800000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 000000000000000000000000000000000000000000000000000088aa000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 000000000000000000000066ccee88220000000000000000000000000000000000000000ff000000 +% 00000000000000000000000000000000000000000000000088cc1100000000000000000000000000 +% 00000000000000000000000000000000000000000000000000dd6600000000000000000000000000 +% 000000000000000000000000000000000000000088ff880000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000dd6600000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000888800000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 000000000000000000000000000000000000000000000000000022ff220000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 0000000000000000000000000044bbff9933000000000000000000000000000000000000ff000000 +% 00000000000000000000000000000000000000000000000011cc8800000000000000000000000000 +% 00000000000000000000000000000000000000000000000066dd0000000000000000000000000000 +% 00000000000000000000000000000000000033ccdd44000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000066dd0000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000888800000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 000000000000000000000000000000000000000000000000000000bb880000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 0000000000000000000000000000002299ffbb4400000000000000000000000000000000ff000000 +% 0000000000000000000000000000000000000000000000000033ee55000000000000000000000000 +% 000000000000000000000000000000000000000000000000dd660000000000000000000000000000 +% 000000000000000000000000000000000077ee881100000000000000000000000000000000000000 +% 000000000000000000000000000000000000000000dd660000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000888800000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000066dd0000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000002288eedd660000000000000000000000000033ff000000 +% 000000000000000000000000000000000000000000000000000077ee110000000000000000000000 +% 000000000000000000000000000000000000000000000066dd000000000000000000000000000000 +% 00000000000000000000000000000022bbee55000000000000000000000000000000000000000000 +% 000000000000000000000000000000000000000066dd000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000888800000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000011ee4400000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 000000000000000000000000000000000000001177ddee88110000000000000000000044ff000000 +% 000000000000000000000000000000000000000000000000000000aabb0000000000000000000000 +% 0000000000000000000000000000000000000000000000dd66000000000000000000000000000000 +% 000000000000000000000000000077eeaa1100000000000000000000000000000000000000000000 +% 0000000000000000000000000000000000000000dd66000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000888800000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000999900006622000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 0000000000000000000000000000000000000000000066ccee9922000000000000000044ff000000 +% 00000000000000000000000000000000000000000000000000000011ee8800000000000000000000 +% 0000000000000000000000000000000000002266000066dd00000000000000000000000000000000 +% 00000000000000000000000011aaee55000000000000000000000000000000000000000000000000 +% 0000000000000000000000000000000000000066dd00000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00338888c8c888888822000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 0000000000000000000000000000000000000000000000000000000033ff70ebff90000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000044aaff994400000000000044ff000000 +% 0000000000000000000000000000000000000000000000000000000044ff33000000000000000000 +% 000000000000000000000000000000000000a7ffeb66dd6600000000000000000000000000000000 +% 000000000000000000000055eebb1100000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000dd8800000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 0077fdffffffffffff66000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 0000000000000000000000000000000000000000000000000000000066fbfdffffcd000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000002299ffbb550000000044ff000000 +% 000000000000000000000000000000000000000000000000000000000088dd110000552200000000 +% 000000000000000000000000000000000000cdfffffdfd6600000000000000000000000000000000 +% 00000000000000000011aaee77000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000066ee1100000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 0022fffffffffffff811000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 000000000000000000000000000000000000000000000000000022ebfbffffffffcd000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 000000000000000000000000000000000000000000000000000000001188eedd66000044cc000000 +% 000000000000000000000000000000000000000000000000000000000000cc9911b6ffc900000000 +% 000000000000000000000000000000000000cdfffffffffbeb220000000000000000000000000000 +% 000000000000000044ddbb2200000000000000000000000000000000000000000000000000000000 +% 000000000000000000000000000000000000dd880000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 0000e9ffffffffffa700000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 000000000000000000000000000000000000000000000000000055fffffffffffff5000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 0000000000000000000000000000000000000000000000000000000000001166ddee8850bb000000 +% 00000000000000000000000000000000000000000000000000000000000022f4f9faffff11000000 +% 000000000000000000000000000000000000f6ffffffffffff550000000000000000000000000000 +% 0000000000001188ff88000000000000000000000000000000000000000000000000000000000000 +% 000000000000000000000000000000000066ee110000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 000090ffffffffff3300000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000080fcffffffffff000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000066bbffe4330000 +% 000000000000000000000000000000000000000000000000000000000011b6fcfffffff966000000 +% 000000000000000000000000000000000000fffffffffffc80000000000000000000000000000000 +% 000000000033cccc3300000000000000000000000000000000000000000000000000000000000000 +% 0000000000000000000000000000000000dd88000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 000044faffffffdd0000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000a0f9ffffffff000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 000000000000000000000000000000000000000000000000000000000000000000000069e4ffbb55 +% 0000000000000000000000000000000000000000000000000000000022f6faffffffffffa7000000 +% 000000000000000000000000000000000000fffffffff9a000000000000000000000000000000000 +% 0000000088ff88000000000000000000000000000000000000000000000000000000000000000000 +% 0000000000000000000000000000000066ee11000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 000000f6fffffb660000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 0000000000000000000000000000000000000000000000000000000000bbfcffffff330000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 000000000000000000000000000000000000000000000000000000000000000000000044bb2288ee +% dd66110000000000000000000000000000000000000000000000000022f6fafffffffffff6000000 +% 000000000000000000000000000000000044fffffffcbb0000000000000000000000000000000000 +% 000033ccdd4400000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000dd8800000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 000000a7fffff8110000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 000000000000000000000000000000000000000000000000000000000011d7fafffb440000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 000000000000000000000000000000000000000000000000000000000000000000000077bb000011 +% 66ddee882200000000000000000000000000000000000000000000000011b6fbfffffffffa440000 +% 000000000000000000000000000000000044f6fffad7110000000000000000000000003333000000 +% 0077ee88110000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000066ee1100000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000066f9ffa7000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000011ebffed550000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 000000000000000000000000000000000000000000000000000000000000000000000088bb000000 +% 000044bbff994400000000000000000000000000000000000000000000000055f6faffffff900000 +% 000000000000000000000000000000000055f2ffeb1100000000000000000000000033f8f8330022 +% bbee5500000000000000000000000000000000000000000000000000000000000000000000000000 +% 000000000000000000000000000000dd880000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000011ffff33000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 0000000000000000000000000000000000000000000000000000000000000033f5ff880000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 000000000000000000000000000000000000000000000000000000000000000000000088bb000000 +% 000000002299eecc66000000000000000000000000000000000000000000000011b6fbffffe90000 +% 000000000000000000000000000000000088fff53300000000000000000000000011daffffe940ee +% aa110000000000000000000000000000000000000000000000000000000000000000000000000000 +% 000000000000000000000000000066ee110000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000033444444 +% 44778888e6f088888888774444444433000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 000000000000000000000000000000000000000000000000000000000000000033ff880011446688 +% 88664411000000000000000000000000000000000000000000000000000000000000000000000000 +% 000000000000000000000000000000000000000000000000000000000000000000000088bb000000 +% 0000000000001188dddd88110000000000225500000000000000000000000000000055f6fbff2200 +% 000000114444448888888888884444441188ff3300000000000000000000000000a0fcfffffbc944 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 0000000000000000000000000000dd88000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000 +% 0000000000000000000000000000000000000000000000000000000033447788aabbeeffffffccbb +% bbbbbbbba7988899bbbbbbbbbbccffffffeebbaa8877443300000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 000000000000000000000000000000000000000000000000000000000033448888c9d0ffffeebbaa +% aabbeeffffccbb888844330000000000000000000000000000000000000000000000000000000000 +% 000000000000000000000000000000000000000000000000000000000000000000000088bb000000 +% 00000000000000000066bbff9922000000ebff8000000000000000000000000000000011b6ff8955 +% 88bbddffffbbbbbbbb8888bbbbbbbbffffe0c98855220000000000000000000066fbfffffffff990 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 0000000000000000000000000066ee11000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000 +% 0000000000000000000000000000000000000000000000115588bbffffddbb998866442200000000 +% 000000000000000000000000000000002244668899bbddffffbb8855110000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000066bbffccbb8888444400000000 +% 0000000044448888bbccffbb66000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000008899000000 +% 00000000000000000000004499ffbb5566fbfffca000000000000000000000000000002277ddffcc +% aa884411000000000000000000000000114488aaccffcc772200000000000033f8ffffffffffffff +% 55000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000dd8800000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000 +% 000000000000000000000000000000000000002277aaddffdd997744000000000000000000000000 +% 000000000000000000000000000000000000000000000000447799ddffddaa772200000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 0000000000000000000000000000000000000000000000001166ddee881100000000000000000000 +% 000000000000000000001188eedd6611000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000008888000000 +% 000000000000000000000000002288eefdfffffff9bb110000000000000000000066ccffcc772200 +% 0000000000000000000000000000000000000000002277ccffcc6600000011dafffffffffff9ffc9 +% 22000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000066dd0000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000 +% 000000000000000000000000000000002277ccffcc88551100000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000115588ccffcc772200000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 000000000000000000000000000000000000000000002288eedd6600000000000000000000000000 +% 0000000000000000000000000066ddee882200000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000008888000000 +% 00000000000000000000000000000070fdfffffffffcd7110000000000000066dddd772200000000 +% 0000000000000000000000000000000000000000000000002277dddd6600a0fdfffffaf6a7661100 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 000000000000000000000011ee660000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000 +% 000000000000000000000000001177ccffcc77220000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000002277ccffcc771100 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000002299ffbb55000000000000000000000000000000 +% 00000000000000000000000000000055bbff99220000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000008888000000 +% 000000000000000000000000000000ebfffffffffffffaeb330000000066dddd6600000000000000 +% 00000000000000000000000000000000000000000000000000000066dde9ffffe990440000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 000000000000000000000088dd000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000002288eecc77220000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000002277ccee88 +% 22000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 0000000000000000000000000000000000000033eeaa330000000000000000000000000000000000 +% 000000000000000000000000000000000033aaee3300000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000008888000000 +% 000000000000000000000000000066fffffffffffffffffff5330011aaee66000000000000000000 +% 000000000000000000000000000000000000000000000000000000000070f6b61100000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 0000000000000000000011ee44000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000 +% 0000000000000000002299ffbb440000000000000000000000000000000000000000000000000000 +% 000000000000000000000000000000000000000000000000000000000000000000000000000044bb +% ff992200000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000033ee8800000000000000000000000000000000000000 +% 0000000000000000000000000000000000000099ee33000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000008888000000 +% 000000000000000000000000000022a7cdcdf6fffffffbf2ffff69ddbb1100000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000011bbdd33000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 0000000000000000000088bb00000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000 +% 000000000000001199ffbb4400000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 44bbff99110000000000000000000000000000000000000000000000000000000000000000000000 +% 000000000000000000000000000000000033ee660000000000000000000000000000000000000000 +% 000000000000000000000000000000000000000066ee330000000000000000000000000000000000 +% 0000000000000000000000000000000000000000000000000000000000000000000000bb88000000 +% 00000000000000000000000000000000000000000044445588b8ff88000000000000000000000000 +% 000000000000000000000000000000000000000000000000000000000000000088ff660000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000022ff4400000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000 +% 00000000000033ddcc33000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 000033ccdd3300000000000000000000000000000000000000000000000000000000000000000000 +% 0000000000000000000000000000000033ee66000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000066ee3300000000000000000000000000000000 +% 0000000000000000000000000000000000000000000000000000000000000000000000bb88000000 +% 00000000000000000000000000000000000000000000000066ff5500000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000055ff6600000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000099aa0000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000 +% 000000000077ff880000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 0000000088ff77000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000033ee6600000000000000000000000000000000000000000000 +% 0000000000000000000000000000000000000000000066ee33000000000000000000000000000000 +% 0000000000000000000000000000000000000000000000000000000000000000000000bb88000000 +% 000000000000000000000000000000000000000000000033ee660000000000000000000000000000 +% 0000000000000000000000000000000000000000000000000000000000000000000066ee33000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 000000000000000033ff220000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000 +% 00000000aaee44000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 000000000044eeaa0000000000000000000000000000000000000000000000000000000000000000 +% 000000000000000000000000000033ee660000000000000000000000000000000000000000000000 +% 000000000000000000000000000000000000000000000066ee330000000000000000000000000000 +% 0000000000000000000000000000000000000000000000000000000000000000000000bb88000000 +% 0000000000000000000000000000000000000000000022ee88000000000000000000000000000000 +% 000000000000000000000000000000000000000000000000000000000000000000000088ee220000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 0000000000000000bb99000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000 +% 00000099cc1100000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000011cc9900000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000009988000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000088990000000000000000000000000000 +% 0000000000000000000000000000000000000000000000000000000000000000000000bb88000000 +% 0000000000000000000000000000000000000000000099aa00000000000000000000000000000000 +% 000000000000000000000000000000000000000000000000000000000000000000000000aa990000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 0000000000000044ff22000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000 +% 000066ee330000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 0000000000000033ee66000000000000000000000000000000000000000000000000000000000000 +% 0000000000000000000000000000ee55000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000055ee0000000000000000000000000000 +% 0000000000000000000000000000000000000000000000000000000000000000000000bb44000000 +% 00000000000000000000000000000000000000000022ff2200000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000022ff2200 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000bb8800000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000 +% 0033ee55000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 000000000000000066ee330000000000000000000000000000000000000000000000000000000000 +% 0000000000000000000000000044ee00000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000ee4400000000000000000000000000 +% 0000000000000000000000000000000000000000000000000000000000000000000000bb44000000 +% 00000000000000000000000000000000000000000099990000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000999900 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000055ee1100000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000 +% 00aa990000000000000000000000bbffee11000088ffffff0000000000000000000000000000bbff +% ee11000088ffffff00000000000000000000000000bbffffff880000000000000000000000000000 +% 00000000000000000099aa0000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000889900000000000000000000000000000000000033ddffcc884400 +% 00000000000000000000000000000000000000000000000000aa8800000000000000000000000000 +% 0000000000000000000000000000000000000000000000000000000000000000000000bb44000000 +% 000000000000000000000000000000000000000000ff330000000000000000000000bbffee110000 +% 88ffffff00000000000000000000000000000000000000000000000000000000000000000033ff00 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 000000000000dd880000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000 +% 00ee44000000000000000000000033ffddcc11000033ff33000000000000000000000000000033ff +% ddcc11000033ff33000000000000000000000000000033ff22000000000000000066000000000000 +% 00000000000000000044ee0000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000dd66000000000000000000000000000000000000ee550033cc7700 +% 6600000000000000000000000000000000000000000000000066dd00000000000000000000000000 +% 0000000000000000000000000000000000000000000000000000000000000000000000bb44000000 +% 000000000000000000000000000000000000000033ff00000000000000000000000033ffddcc1100 +% 0033ff3300000000000000000000000000000000000000000000000000000000000000000000ff33 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 000000000066dd110000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000 +% 33ff00000000000000000000000000ff33ee99000000ff00000000000000000000000000000000ff +% 33ee99000000ff00000000000000000000000000000000ff000000000000000000dd000000000000 +% 00000000000000000000ff3300000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000022ff11000000000000000000000000000000000000ee110000117700 +% dd00000000000000000000000000000000000000000000000011ff22000000000000000000000000 +% 0000000000000000000000000000000000000000000000000000000000000000000000bb44000000 +% 000000000000000000000000000000000000000055cc00000000000000000000000000ff33ee9900 +% 0000ff0000000000000000000000000000000000000000000000000000000000000000000000cc55 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 0000000011dd66000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000 +% 77aa00000000000000000000000000ff0033ee880000ff000011bbffbb110044cc99ddff880000ff +% 0033ee880000ff000066ddffbb110033ddffffff880000ff0044cc99ddff880088ffff8800000000 +% 00000000000000000000bb7700000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000077bb0000000000000000000000000000000000000066cc4400000088 +% ffff8855dd44aa99000000000000000000000000000000000000bb77000000000000000000000000 +% 0000000000000000000000000000000000000000000000000000000000000000000000ee44000000 +% 000000000000000000000000000000000000000088aa00000000000000000000000000ff0033ee88 +% 0000ff000011bbffbb110044cc99ddff88000066ddffbb110000000000000000000000000000aa88 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 0000000088dd00000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000 +% 77aa00000000000000000000000000ff000055ff6600ff0000aa660099aa0000ff660033ff0000ff +% 000055ff6600ff0044ffffffff8800dd220077cc000000ff0000ff660033ff0000ff000000000000 +% 00000000000000000000bb7700000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000077bb00000000000000000000000000000000000000001188aa440000 +% ff000000ff000000000000000000000000000000000000000000bb77000000000000000000000000 +% 0000000000000000000000000000000000000000000000000000000000000000000000ff44000000 +% 000000000000000000000000000000000000000088aa00000000000000000000000000ff000055ff +% 6600ff0000aa660099aa0000ff660033ff0044ffffffff880000000000000000000000000000aa88 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000011ee5500000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000 +% 33ff00000000000000000000000000ff00000066ee33ff0000ff000011ff0000ff000000ff0000ff +% 00000066ee33ff0088770000000000ff770022ee000000ff0000ff000000ff0000ff000000000000 +% 00000000000000000000ff3300000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000022ff1100000000000000000000000000000000000000000011996600 +% ff000000ff000000000000000000000000000000000000000011ff22000000000000000000000000 +% 0000000000000000000000000000000000000000000000000000000000000000000000ff44000000 +% 000000000000000000000000000000000000000055cc00000000000000000000000000ff00000066 +% ee33ff0000ff000011ff0000ff000000ff008877000000000000000000000000000000000000cc55 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000088bb0000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000 +% 00ee44000000000000000000000000ff0000000088eeff0000ff220000ff0000ff000000ff0000ff +% 0000000088eeff00aa99000000220066ddffdd55000000ff0000ff000000ff0000ff000000000000 +% 00000000000000000044ee0000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000dd660000000000000000000000000000000000443300000000ff00 +% ff000000ff000000000000000000000000000000000000000066dd00000000000000000000000000 +% 0000000000000000000000000000000000000000000000000000000000000000000000ff44000000 +% 000000000000000000000000000000000000000033ff00000000000000000000000000ff00000000 +% 88eeff0000ff220000ff0000ff000000ff00aa99000000220000000000000000000000000000ff33 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 000022ff440000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000 +% 00aa99000000000000000000000011ff440000000099ff0000aa990077990011ff110011ff1111ff +% 440000000099ff0066ff55004466008811000000000022ff2211ff110011ff1100ff110000000000 +% 00000000000000000099aa0000000000000000000000000000000000000000000000000000000000 +% 000000000000000000000000008899000000000000000000000000000000000044ee66000077dd00 +% ff110011ff2200000000000000000000000000000000000000aa8800000000000000000000000000 +% 0000000000000000000000000000000000000000000000000000000000000000000000ff44000000 +% 000000000000000000000000000000000000000000ff33000000000000000000000011ff44000000 +% 0099ff0000aa990077990011ff110011ff1166ff550044660000000000000000000000000033ff00 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 000099bb000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000 +% 0033ee5500000000000000000000bbffff880000000099000011bbffbb1100bbffff44ffffbbbbff +% ff880000000099000088ffee880033eeffffbbbb55bbffffffe0ffff44ffffbb00aaff7700000000 +% 000000000000000066ee330000000000000000000000000000000000000000000000000000000000 +% 0000000000000000000000000044ee000000000000000000000000000000000011cc55ddffaa3300 +% aaff77ffffff88000000000000000000000000000000000000ee4400000000000000000000000000 +% 0000000000000000000000000000000000000000000000000000000000000000000000ff22000000 +% 00000000000000000000000000000000000000000099990000000000000000000000bbffff880000 +% 000099000011bbffbb1100bbffff44ffffbb0088ffee880000000000000000000000000000999900 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 0022ff33000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000 +% 000066ee330000000000000000000000000000000000000000000000000000000000000000000000 +% 0000000000000000000000000000333322444455ff00000000000000000000000000000000000000 +% 0000000000000033ee66000000000000000000000000000000000000000000000000000000000000 +% 0000000000000000000000000000ee55000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000055ee0000000000000000000000000000 +% 0000000000000000000000000000000000000000000000000000000000000000000000ff00000000 +% 00000000000000000000000000000000000000000022ff2200000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000022ff2200 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00bb9900000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000 +% 00000099cc1100000000000000000000000000000000000000000000000000000000000000000000 +% 0000000000000000000000000000ee55000022889900000000000000000000000000000000000000 +% 00000000000011cc9900000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000009988000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000088990000000000000000000000000000 +% 0000000000000000000000000000000000000000000000000000000000000000000000ff00000000 +% 0000000000000000000000000000000000000000000099aa00000000000000000000000000000000 +% 000000000000000000000000000000000000000000000000000000000000000000000000aa990000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 55ee1100000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000 +% 00000000aaee44000000000000000000000000000000000000000000000000000000000000000000 +% 000000000000000000000000000066ddffffbb660000000000000000000000000000000000000000 +% 000000000044eeaa0000000000000000000000000000000000000000000000000000000000000000 +% 000000000000000000000000000033ee660000000000000000000000000000000000000000000000 +% 000000000000000000000000000000000000000000000066ee330000000000000000000000000000 +% 0000000000000000000000000000000000000000000000000000000000000000000000ff00000000 +% 0000000000000000000000000000000000000000000022ee88000000000000000000000000000000 +% 000000000000000000000000000000000000000000000000000000000000000000000088ee220000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% dd880000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000 +% 000000000077ff880000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 0000000088ff77000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000033ee6600000000000000000000000000000000000000000000 +% 0000000000000000000000000000000000000000000066ee33000000000000000000000000000000 +% 0000000000000000000000000000000000000000000000000000000000000000000000ff00000000 +% 000000000000000000000000000000000000000000000033ee660000000000000000000000000000 +% 0000000000000000000000000000000000000000000000000000000000000000000066ee33000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000088 +% dd000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000 +% 00000000000033ddcc33000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 000033ccdd3300000000000000000000000000000000000000000000000000000000000000000000 +% 0000000000000000000000000000000033ee66000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000066ee3300000000000000000000000000000000 +% 0000000000000000000000000000000000000000000000000000000000000000000011ff00000000 +% 00000000000000000000000000000000000000000000000066ff5500000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000055ff6600000000 +% 000000000000000000000000000000000000000000000000000000000000000000000000000022ee +% 44000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000 +% 000000000000001199ffbb4400000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 44bbff99110000000000000000000000000000000000000000000000000000000000000000000000 +% 000000000000000000000000000000000033ee660000000000000000000000000000000000000000 +% 000000000000000000000000000000000000000066ee330000000000000000000000000000000000 +% 0000000000000000000000000000000000000000000000000000000000000000000044ff00000000 +% 0000000000000000000000000000000000000000000000000066ff88000000000000000000000000 +% 000000000000000000000000000000000000000000000000000000000000000088ff660000000000 +% 0000000000000000000000000000000000000000000000000000000000000000000000000000aaaa +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000 +% 0000000000000000002299ffbb440000000000000000000000000000000000000000000000000000 +% 000000000000000000000000000000000000000000000000000000000000000000000000000044bb +% ff992200000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000033ee8800000000000000000000000000000000000000 +% 0000000000000000000000000000000000000099ee33000000000000000000000000000000000000 +% 0000000000000000000000000000000000000000000000000000000000000000000044ff00000000 +% 000000000000000000000000000000000000000000000000000033ddbb1100000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000011bbdd33000000000000 +% 0000000000000000000000000000000000000000000000000000000000000000000000000044ff22 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000002288eecc77220000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000002277ccee88 +% 22000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 0000000000000000000000000000000000000033eeaa330000000000000000000000000000000000 +% 000000000000000000000000000000000033aaee3300000000000000000000000000000000000000 +% 0000000000000000000000000000000000000000000000000000000000000000000044ff00000000 +% 00000000000000000000000000000000000000000000000000000011aaee66000000000000000000 +% 000000000000000000000000000000000000000000000000000000000066eeaa1100000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000dd8800 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000 +% 000000000000000000000000001177ccffcc77220000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000002277ccffcc771100 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000002299ffbb55000000000000000000000000000000 +% 00000000000000000000000000000055bbff99220000000000000000000000000000000000000000 +% 0000000000000000000000000000000000000000000000000000000000000000000044ff00000000 +% 000000000000000000000000000000000000000000000000000000000066dddd6600000000000000 +% 00000000000000000000000000000000000000000000000000000066dddd66000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000077dd1100 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000 +% 000000000000000000000000000000002277ccffcc88551100000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000115588ccffcc772200000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 000000000000000000000000000000000000000000002288eedd6600000000000000000000000000 +% 0000000000000000000000000066ddee882200000000000000000000000000000000000000000000 +% 0000000000000000000000000000000000000000000000000000000000000000000044ff00000000 +% 0000000000000000000000000000000000000000000000000000000000000066dddd772200000000 +% 0000000000000000000000000000000000000000000000002277dddd660000000000000000000000 +% 000000000000000000000000000000000000000000000000000000000000000000000011ee550000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000 +% 000000000000000000000000000000000000002277aaddffdd997744000000000000000000000000 +% 000000000000000000000000000000000000000000000000447799ddffddaa772200000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 0000000000000000000000000000000000000000000000001166ddee881100000000000000000000 +% 000000000000000000001188eedd6611000000000000000000000000000000000000000000000000 +% 0000000000000000000000000000000000000000000000000000000000000000000044bb00000000 +% 00000000000000000000000000000000000000000000000000000000000000000066ccffcc772200 +% 0000000000000000000000000000000000000000002277ccffcc6600000000000000000000000000 +% 000000000000000000000000000000000000000000000000000000000000000000000099bb000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000 +% 0000000000000000000000000000000000000000000000115588bbffffddbb998866442200000000 +% 000000000000000000000000000000002244668899bbddffffbb8855110000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000066bbffccbb8888444400000000 +% 0000000044448888bbccffbb66000000000000000000000000000000000000000000000000000000 +% 0000000000000000000000000000000000000000000000000000000000000000000044bb00000000 +% 00000000000000000000000000000000000000000000000000000000000000000000002277ccffcc +% aa884411000000000000000000000000114488aaccffcc7722000000000000000000000000000000 +% 0000000000000000000000000000000000000000000000000000000000000000000044ff22000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000 +% 0000000000000000000000000000000000000000000000000000000033447788aabbeeffffffccbb +% bbbbbbbb99888899bbbbbbbbbbd3ffffffeebbaa8877443300000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 000000000000000000000000000000000000000000000000000000000033448888bbccffffeebbaa +% aabbeeffffccbb888844330000000000000000000000000000000000000000000000000000000000 +% 0000000000000000000000000000000000000000000000000000000000000000000044bb00000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000002255 +% 88bbe2ffffbbbbbbbb8888bbbbbbbbffffddbb885522000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000cc8800000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000033444444 +% 4477888888888888888877449bda4433000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000011446688 +% 88b8a811000000000000000000000000000000000000000000000000000000000000000000000000 +% 0000000000000000000000000000000000000000000000000000000000000000000044bb00000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 0000dd70444444888888888888444444110000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000066ee1100000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000022ff2200000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 0088bb00000000000000000000000000000000000000000000000000000000000000000000000000 +% 0000000000000000000000000000000000000000000000000000000000000000000044bb00000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 0044ee11000000000000000000000000000000000000000000000000000000000000000000000000 +% 000000000000000000000000000000000000000000000000000000000000000011ee660000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000aa8800000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 0066bb00000000000000000000000000000000000000000000000000000000000000000000000000 +% 0000000000000000000000000000000000000000000000000000000000000000000077bb00000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00999900000000000000000000000000000000000000000000000000000000000000000000000000 +% 000000000000000000000000000000000000000000000000000000000000000088bb000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 0000000000000000000000000066dd00000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 0044bb00000000000000000000000000000000000000000000000000000000000000000000000000 +% 0000000000000000000000000000000000000000000000000000000000000000000088bb00000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 22ff3300000000000000000000000000000000000000000000000000000000000000000000000000 +% 0000000000000000000000000000000000000000000000000000000000000033ff33000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 0000000000000000000000000011ff33000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 0044ff00000000000000000000000000000000000000000000000000000000000000000000000000 +% 0000000000000000000000000000000000000000000000000000000000000000000088bb00000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 88bb0000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000bb9900000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 0000000000000000000000000000aa88000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 0022ff00000000000000000000000000000000000000000000000000000000000000000000000000 +% 0000000000000000000000000000000000000000000000000000000000000000000088bb00000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% dd660000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000055ee1100000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 000000000000000000000000000055dd000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 0000ff00000000000000000000000000000000000000000000000000000000000000000000000000 +% 0000000000000000000000000000000000000000000000000000000000000000000088bb00000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000055 +% ee000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 000000000000000000000000000000000000000000000000000000000011dd770000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 000000000000000000000000000000ee440000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 0000ff44000000000000000000000000000000000000000000000000000000000000000000000000 +% 0000000000000000000000000000000000000000000000000000000000000000000088aa00000000 +% 000000000000000000000000000000000000000000000000000000000000000000000000000000bb +% 88000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 000000000000000000000000000000000000000000000000000000000088cc000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000099990000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 0000ee44000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000888800000000 +% 000000000000000000000000000000000000000000000000000000000000000000000000000022ff +% 22000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 0000000000000000000000000000000000000000000000000000000022ff44000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000055ee0000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 0000bb44000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000888800000000 +% 000000000000000000000000000000000000000000000000000000000000000000000000000088aa +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000bb9900000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000dd5500000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 0000bb77000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000888800000000 +% 0000000000000000000000000000000000000000000000000000000000000000000000000000ee55 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000044ee2200000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000889900000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 0000bb88000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000888800000000 +% 0000000000000000000000000000000000000000000000000000000000000000000000000066dd00 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 000000000000000000000000000000000000000000000000000000dd880000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 0000000000000000000000000000000033ff11000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00008888000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000888800000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000cc8800 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 000000000000000000000000000000000000000000000000000088cc000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 0000000000000000000000000000000000dd66000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00008899000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000bb8800000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000033ff1100 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 0000000000000000000000000000000000000000000000000033ff44000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 000000000000000000000000000000000077cc000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 000088bb000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000bb8800000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000099990000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000cc8800000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 000000000000000000000000000000000022ff220000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 000055bb000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000bb8800000000 +% 000000000000000000000000000000000000000000000000000000000000000000000011ee440000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000088dd1100000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 000000000000000000000000000000000000aa880000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 000044cc000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000bb8800000000 +% 000000000000000000000000000000000000000000000000000000000000000000000066dd000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 000000000000000000000000000000000000000000000033ff440000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000055ee0000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 000044ff000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000bb8800000000 +% 0000000000000000000000000000000000000000000000000000000000000000000000cc77000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 0000000000000000000000000000000000000000000000cc88000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000dd6600000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 000022ff000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000bb6600000000 +% 0000000000000000000000000000000000000000000000000000000000000000000044ee11000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 0000000000000000000000000000000000000000000088dd11000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 0000000000000000000000000000000000000088aa00000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 000000ff000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000bb4400000000 +% 00000000000000000000000000000000000000000000000000000000000000000000999900000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000033ff4400000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 0000000000000000000000000000000000000022ff22000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 000000ff440000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000bb4400000000 +% 00000000000000000000000000000000000000000000000000000000000000000011ff3300000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 000000000000000000000000000000000000000000cc880000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 0000000000000000000000000000000000000000bb88000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 000000ff440000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000bb4400000000 +% 00000000000000000000000000000000000000000000000000000000000000000077cc0000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 000000000000000000000000000000000000000088dd110000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 000000000000000000000000000000000000000066dd000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 000000bb440000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000bb4400000000 +% 000000000000000000000000000000000000000000000000000000000000000000dd660000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 0000000000000000000000000000000000000033ff44000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 000000000000000000000000000000000000000011ee440000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 000000bb660000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000cc4400000000 +% 000000000000000000000000000000000000000000000000000000000000000044ee110000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000cc8800000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000099990000662200000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 000000bb880000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000ff4400000000 +% 00000000000000000000000000000000000000000000000000000000000000009999000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000088dd1100000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000033ff70ebff9000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 338888c8c88888882200000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000ff4400000000 +% 0000000000000000000000000000000000000000000000000000000000000011ff33000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 000000000000000000000000000000000033ff440000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000066fbfdffffcd00000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 77fdffffffffffff6600000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000ff4400000000 +% 0000000000000000000000000000000000000000000000000000000000000077cc00000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 0000000000000000000000000000000000bb88000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 0000000000000000000000000000000000000022ebfbffffffffcd00000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 22fffffffffffff81100000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000ff4400000000 +% 00000000000000000000000000000000000000000000000000000000000000dd6600000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 0000000000000000000000000000000077dd11000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 0000000000000000000000000000000000000055fffffffffffff500000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00e9ffffffffffa70000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000ff4400000000 +% 00000000000000000000000000000000000000000000000000000000000055ee1100000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000022ee5500000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 000000000000000000000000000000000000000080fcffffffffff00000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 0090ffffffffff330000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000ff1100000000 +% 000000000000000000000000000000000000000000000000000000000000aa880000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 000000000000000000000000000000bbaa0000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 000000000000000000000000000000000000000000a0f9ffffffff00000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 0044faffffffdd000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000ff0000000000 +% 000000000000000000000000000000000000000000000000000000000022ff220000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 000000000000000000000000000077ee110000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000bbfcffffff33000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 0000f6fffffb66000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000ff0000000000 +% 000000000000000000000000000000000000000000000000000000000088bb000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 0000000000000000000000000022ee55000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 0000000000000000000000000000000000000000000011d7fafffb44000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 0000a7fffff811000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000ff0000000000 +% 0000000000000000000000000000000000000000000000000000000000dd66000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000bbaa00000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 000000000000000000000000000000000000000000000011ebffed55000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 000066f9ffa700000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000ff0000000000 +% 0000000000000000000000000000000000000000000000000000000055ee00000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000077ee1100000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000033f5ff88000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 000011ffff3300000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000022ff0000000000 +% 00000000000000000000000000000000000000000000000000000000aa8800000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 000000000000000000000022ee550000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 0000000000000000000000000000000000000000000000000033ff88001144668888664411000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 000011d7eb8888664411000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000044ff0000000000 +% 00000000000000000000000000000000000000000000000000000022ff2200000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 0000000000000000000000bbaa000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 0000000000000000000000000000000000000000000033448888c9d0ffffeebbaaaabbeeffffccbb +% 88884433000000000000000000000000000000000000000000000000000000000000000000000000 +% 000000000000000000000000000000000000000000000000000000000000000000000033448888bb +% ccfffff1c4aaaabbeeffffccbb888844330000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000044ff0000000000 +% 00000000000000000000000000000000000000000000000000000088bb0000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 0000000000000000000077ee11000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 000000000000000000000000000000000000000066bbffccbb888844440000000000000000444488 +% 88bbccffbb6600000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000066bbffccbb8888 +% 4444000000000000000044448888bbccffbb66000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000044ff0000000000 +% 000000000000000000000000000000000000000000000000000000dd660000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000033ee5500000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000001166ddee88110000000000000000000000000000000000 +% 0000001188eedd661100000000000000000000000000000000000000000000000000000000000000 +% 0000000000000000000000000000000000000000000000000000000000001166ddee881100000000 +% 000000000000000000000000000000001188eedd6611000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000044ff0000000000 +% 000000000000000000000000000000000000000000000000000055ee000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 000000000000000011cc990000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 0000000000000000000000000000002288eedd660000000000000000000000000000000000000000 +% 00000000000066ddee88220000000000000000000000000000000000000000000000000000000000 +% 000000000000000000000000000000000000000000000000000000002288eedd6600000000000000 +% 0000000000000000000000000000000000000066ddee882200000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000044ff0000000000 +% 0000000000000000000000000000000000000000000000000000aa88000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 000000000000000099cc110000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 000000000000000000000000002299ffbb5500000000000000000000000000000000000000000000 +% 000000000000000055bbff9922000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000002299ffbb55000000000000000000 +% 00000000000000000000000000000000000000000055bbff99220000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000044bb0000000000 +% 0000000000000000000000000000000000000000000000000022ff22000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 0000000000000066ee33000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000033eeaa33000000000000000000000000000000000000000000000000 +% 0000000000000000000033aaee330000000000000000000000000000000000000000000000000000 +% 0000000000000000000000000000000000000000000000000033eeaa330000000000000000000000 +% 000000000000000000000000000000000000000000000033aaee3300000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000044bb0000000000 +% 0000000000000000000000000000000000000000000000000088bb00000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000033ee6600000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 000000000000000000000033ee880000000000000000000000000000000000000000000000000000 +% 00000000000000000000000099ee3300000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000033ee8800000000000000000000000000 +% 0000000000000000000000000000000000000000000000000099ee33000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000044bb0000000000 +% 00000000000000000000000000000000000000000000000000dd6600000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 000000000011cc990000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 0000000000000000000033ee66000000000000000000000000000000000000000000000000000000 +% 0000000000000000000000000066ee33000000000000000000000000000000000000000000000000 +% 000000000000000000000000000000000000000000000033ee660000000000000000000000000000 +% 000000000000000000000000000000000000000000000000000066ee330000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000044bb0000000000 +% 00000000000000000000000000000000000000000000000055ee0000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 000000000099cc000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000033ee6600000000000000000000000000000000000000000000000000000000 +% 000000000000000000000000000066ee330000000000000000000000000000000000000000000000 +% 0000000000000000000000000000000000000000000033ee66000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000066ee3300000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000044bb0000000000 +% 000000000000000000000000000000000000000000000000aa880000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 0000000066ee22000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 000000000000000033ee660000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000066ee3300000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000033ee6600000000000000000000000000000000 +% 0000000000000000000000000000000000000000000000000000000066ee33000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000066bb0000000000 +% 000000000000000000000000000000000000000000000022ff220000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000033ee5500000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 0000000000000033ee66000000000000000000000000000000000000000000000000000000000000 +% 0000000000000000000000000000000066ee33000000000000000000000000000000000000000000 +% 000000000000000000000000000000000000000033ee660000000000000000000000000000000000 +% 000000000000000000000000000000000000000000000000000000000066ee330000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000088bb0000000000 +% 000000000000000000000000000000000000000000000088bb000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 000011cc880000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000998800000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000008899000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000009988000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000088990000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000088bb0000000000 +% 0000000000000000000000000000000000000000000000dd66000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 0000aacc000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000ee5500000000000000000000000000000000000000000000000000000000000000 +% 000000000000000000000000000000000055ee000000000000000000000000000000000000000000 +% 0000000000000000000000000000000000000000ee55000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000055ee0000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000088bb0000000000 +% 0000000000000000000000000000000000000000000055ee00000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 0077ee22000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000044ee0000000000000000000000000022000000000000000000000000000000000000 +% 001166000000000000000000000000000000ee440000000000000000000000000000000000000000 +% 0000000000000000000000000000000000000044ee00000000000000000000000000000000000000 +% 00226600000000000000000000000000000000000000000000000000000000ee4400000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000088bb0000000000 +% 00000000000000000000000000000000000000000000aa8800000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 33ff5500000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 000000000000889900000000000000000000bbffff22444488220000000000000000000000000000 +% 0033ff000000000000000000000000000000aa880000000000000000000000000000000000000000 +% 000000000000000000000000000000000000008899000000000000000000000000001199eeffdd88 +% 7733ff00000000000000000000000000000000000000000000000000000000aa8800000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000088bb0000000000 +% 00000000000000000000000000000000000000000022ff2200000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000011 +% dd880000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 000000000000dd66000000000000000000000033ff00000011dd0000000000000000000000000000 +% 0000ff00000000000000000000000000000066dd0000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000dd6600000000000000000000000011cc88110033aa +% 8800ff0000000000000000000000000000000000000000000000000000000066dd00000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000088880000000000 +% 00000000000000000000000000000000000000000088bb0000000000000000000000000000000000 +% 000000000000000000000000000000000000000000000000000000000000000000000000000000aa +% cc000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 000000000022ff11000000000000000000000000ff00000011ff0000000000000000000000000000 +% 0000ff00000000000000000000000000000011ff2200000000000000000000000000000000000000 +% 00000000000000000000000000000000000022ff1100000000000000000000000099880000000000 +% 9900ff0000000000000000000000000000000000000000000000000000000011ff22000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000088880000000000 +% 000000000000000000000000000000000000000000dd660000000000000000000000000000000000 +% 000000000000000000000000000000000000000000000000000000000000000000000000000077ee +% 11000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 000000000077bb00000000000000000000000000ff0000229988000011bbffbb11000011bbffbb11 +% 0000ff00000000000000000000000000000000bb7700000000000000000000000000000000000000 +% 00000000000000000000000000000000000077bb00000000000000000000000000ee220000000000 +% 0000ff88eeff88000088eeff88000055dd44aa99000000000000000000000000bb77000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000088880000000000 +% 000000000000000000000000000000000000000055ee000000000000000000000000000000000000 +% 0000000000000000000000000000000000000000000000000000000000000000000000000033ff44 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 000000000077bb00000000000000000000000000ffffffffaa110000aa660099aa0000aa660099aa +% 0000ff00000000000000000000000000000000bb7700000000000000000000000000000000000000 +% 00000000000000000000000000000000000077bb00000000000000000000000000ff000000000000 +% 0000ff660033ff0000aa0033ff000000ff000000000000000000000000000000bb77000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000088880000000000 +% 0000000000000000000000000000000000000000aa88000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000011dd8800 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 000000000022ff11000000000000000000000000ff00003399bb0000ff000011ff0000ff000011ff +% 0000ff00000000000000000000000000000011ff2200000000000000000000000000000000000000 +% 00000000000000000000000000000000000022ff11000000000000000000000000ee220000000000 +% 0000ff000000ff0000001166ff000000ff000000000000000000000000000011ff22000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000088880000000000 +% 0000000000000000000000000000000000000011ff22000000000000000000000000000000000000 +% 000000000000000000000000000000000000000000000000000000000000000000000000aabb0000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 000000000000dd66000000000000000000000000ff00000000ff0000ff220000ff0000ff220000ff +% 0000ff00000000000000000000000000000066dd0000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000dd6600000000000000000000000099880000000000 +% 0000ff000000ff0000333300ff000000ff000000000000000000000000000066dd00000000000000 +% 000000000000000000000000000000000000000000000000000000000000000000aa880000000000 +% 0000000000000000000000000000000000000077cc00000000000000000000000000000000000000 +% 000000000000000000000000000000000000000000000000000000000000000000000088ee110000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 0000000000008899000000000000000000000033ff11002288bb0000aa990077990000aa99007799 +% 0011ff220000000000000000000000000000aa880000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000889900000000000000000000000022ee8822001155 +% 7711ff110011ff1100ee3344ff110011ff2200000000000000000000000000aa8800000000000000 +% 000000000000000000000000000000000000000000000000000000000000000000bb880000000000 +% 00000000000000000000000000000000000000dd6600000000000000000000000000000000000000 +% 0000000000000000000000000000000000000000000000000000000000000000000044ff44000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000044ee00000000000000000000bbffffffffffaa11000011bbffbb11000011bbffbb11 +% 00bbffff8800000000000000000000000000ee440000000000000000000000000000000000000000 +% 0000000000000000000000000000000000000044ee000000000000000000000000002299eeffdd88 +% 00bbffff88ffffbb00aaee88dddd22ffffff88000000000000000000000000ee4400000000000000 +% 000000000000000000000000000000000000000000000000000000000000000000bb880000000000 +% 00000000000000000000000000000000000044ee1100000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000011ee8800000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000ee5500000000000000000000000000000000000000000000000000000000000000 +% 000000000000000000000000000000000055ee000000000000000000000000000000000000000000 +% 0000000000000000000000000000000000000000ee55000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000055ee0000000000000000 +% 000000000000000000000000000000000000000000000000000000000000000000bb880000000000 +% 00000000000000000000000000000000000099990000000000000000000000000000000000000000 +% 000000000000000000000000000000000000000000000000000000000000000000bbbb0000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000998800000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000008899000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000009988000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000088990000000000000000 +% 000000000000000000000000000000000000000000000000000000000000000000bb880000000000 +% 000000000000000000000000000000000011ff330000000000000000000000000000000000000000 +% 000000000000000000000000000000000000000000000000000000000000000088ee110000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 0000000000000033ee66000000000000000000000000000000000000000000000000000000000000 +% 0000000000000000000000000000000066ee33000000000000000000000000000000000000000000 +% 000000000000000000000000000000000000000033ee660000000000000000000000000000000000 +% 000000000000000000000000000000000000000000000000000000000066ee330000000000000000 +% 000000000000000000000000000000000000000000000000000000000000000000bb880000000000 +% 000000000000000000000000000000000077cc000000000000000000000000000000000000000000 +% 0000000000000000000000000000000000000000000000000000000000000044ff33000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 000000000000000033ee660000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000066ee3300000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000033ee6600000000000000000000000000000000 +% 0000000000000000000000000000000000000000000000000000000066ee33000000000000000000 +% 000000000000000000000000000000000000000000000000000000000000000000bb440000000000 +% 0000000000000000000000000000000000dd66000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000022ee7700000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000033ee6600000000000000000000000000000000000000000000000000000000 +% 000000000000000000000000000066ee850000000000000000000000000000000000000000000000 +% 0000000000000000000000000000000000000000000033ee66000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000066ee3300000000000000000000 +% 000000000000000000000000000000000000000000000000000000000000000000bb440000000000 +% 0000000000000000000000000000000044ee11000000000000000000000000000000000000000000 +% 000000000000000000000000000000000000000000000000000000000011cc990000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 0000000000000000000033ee66000000000000000000000000000000000000000000000000000000 +% 0000000000000000000000000066ee4eddee88110000000000000000000000000000000000000000 +% 000000000000000000000000000000000000000000000033ee660000000000000000000000000000 +% 000000000000000000000000000000000000000000000000000066ee330000000000000000000000 +% 000000000000000000000000000000000000000000000000000000000000000000bb440000000000 +% 00000000000000000000000000000000999900000000000000000000000000000000000000000000 +% 0000000000000000000000000000000000000000000000000000000011ccbb000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 000000000000000000000033ee880000000000000000000000000000000000000000000000000000 +% 00000000000000000000000099ee33000066bbee9922000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000033ee8800000000000000000000000000 +% 0000000000000000000000000000000000000000000000000099ee33000000000000000000000000 +% 000000000000000000000000000000000000000000000000000000000000000000bb440000000000 +% 00000000000000000000000000000011ff3300000000000000000000000000000000000000000000 +% 0000000000000000000000000000000000000000000000000000000099cc11000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000033eeaa33000000000000000000000000000000000000000000000000 +% 0000000000000000000033aaee33000000000044bbff993300000000000000000000000000000000 +% 0000000000000000000000000000000000000000000000000033eeaa330000000000000000000000 +% 000000000000000000000000000000000000000000000033aaee3300000000000000000000000000 +% 000000000000000000000000000000000000000000000000000000000000000000bb440000000000 +% 00000000000000000000000000000066dd0000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000099dd1100000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 000000000000000000000000002299ffbb5500000000000000000000000000000000000000000000 +% 000000000000000055bbff992200000000000000002299ffbb440000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000002299ffbb55000000000000000000 +% 00000000000000000000000000000000000000000055bbff99220000000000000000000000000000 +% 000000000000000000000000000000000000000000000000000000000000000000ee440000000000 +% 000000000000000000000000000000cc770000000000000000000000000000000000000000000000 +% 000000000000000000000000000000000000000000000000000077ee330000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 0000000000000000000000000000002288eedd660000000000000000000000000000000000000000 +% 00000000000066ddee88220000000000000000000000002288eedd66000000000000000000000000 +% 000000000000000000000000000000000000000000000000000000002288eedd6600000000000000 +% 0000000000000000000000000000000000000066ddee882200000000000000000000000000000000 +% 000000000000000000000000000000000000000000000000000000000000000000ff440000000000 +% 000000000000000000000000000033ff110000000000000000000000000000000000000000000000 +% 0000000000000000000000000000000000000000000000000066ee33000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000001166ddee88110000000000000000000000000000000000 +% 0000001188eedd6611000000000000000000000000000000001177dddd8811000000000000000000 +% 0000000000000000000000000000000000000000000000000000000000001166ddee881100000000 +% 000000000000000000000000000000001188eedd6640000000000000000000000000000000000000 +% 000000000000000000000000000000000000000000000000000000000000000000ff440000000000 +% 00000000000000000000000000009999000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000044ff6600000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 000000000000000000000000000000000000000066bbffccbb888844440000000000000000444488 +% 88bbccffbb660000000000000000000000000000000000000000000066ccee882200000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000066bbffccbb8888 +% 4444000000000000000044448888bbccffbb660044ff440000000000000000000000000000000000 +% 000000000000000000000000000000000000000000000000000000000000000000ff440000000000 +% 0000000000000000000000000011ee44000000000000000000000000000000000000000000000000 +% 000000000000000000000000000000000000000000000033ee660000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 0000000000000000000000000000000000000000000033448888bbccffffeebbaaaabbeeffffccbb +% 88884433000000000000000000000000000000000000000000000000000044bbff99330000000000 +% 000000000000000000000000000000000000000000000000000000000000000000000033448888bb +% ccffffeebbaaaabbeeffffccbb888844330000000066ee3300000000000000000000000000000000 +% 000000000000000000000000000000000000000000000000000000000000000000ff440000000000 +% 0000000000000000000000000066dd00000000000000000000000000000000000000000000000000 +% 0000000000000000000000000000000000000000000033ee88000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000001144668888664411000000 +% 00000000000000000000000000000000000000000000000000000000000000002299ffbb44000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 0000114466888866441100000000000000000000000088ee33000000000000000000000000000000 +% 000000000000000000000000000000000000000000000000000000000000000000ff440000000000 +% 00000000000000000000000000cc7700000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000011cc9900000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 000000000000000000000000000000000000000000000000000000000000000000002288eedd6600 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 000000000000000000000000000000000000000000000099dd110000000000000000000000000000 +% 000000000000000000000000000000000000000000000000000000000000000000ff000000000000 +% 00000000000000000000000022ff2200000000000000000000000000000000000000000000000000 +% 000000000000000000000000000000000000000011ccbb0000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 0000000000000000000000000000000000000000000000000000000000000000000000001177dddd +% 88110000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000099cc1100000000000000000000000000 +% 000000000000000000000000000000000000000000000000000000000000000000ff000000000000 +% 00000000000000000000000088aa0000000000000000000000000000000000000000000000000000 +% 0000000000000000000000000000000000000000aacc110000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000066 +% ccee9922000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000011cccc00000000000000000000000000 +% 000000000000000000000000000000000000000000000000000000000000000000ff000000000000 +% 000000000000000000000000ee550000000000000000000000000000000000000000000000000000 +% 0000000000000000000000000000000000000099dd11000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 0044aaff994400000000000000000000000000000000000000000000000000000000000000000000 +% 0000000000000000000000000000000000000000000000000011cc99000000000000000000000000 +% 000000000000000000000000000000000000000000000000000000000000000000ff000000000000 +% 000000000000000000000066dd000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000088ee3300000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 0000002299ffbb550000000000000000000000000000000000000000000000000000000000000000 +% 000000000000000000000000000000000000000000000000000011ee990000000000000000000000 +% 000000000000000000000000000000000000000000000000000000000000000000ff000000000000 +% 0000000000000000000000aa88000000000000000000000000000000000000000000000000000000 +% 000000000000000000000000000000000066ee330000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000001188eedd66110000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000033ee8800000000000000000000 +% 000000000000000000000000000000000000000000000000000000000000000033ff000000000000 +% 0000000000000000000022ff22000000000000000000000000000000000000000000000000000000 +% 0000000000000000000000000000000055ff66000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 000000000000001166ddee8811000000000000000000000000000000000000000000000000000000 +% 0000000000000000000000000000000000000000000000000000000033ee66000000000000000000 +% 000000000000000000000000000000000000000000000000000000000000000044ff000000000000 +% 0000000000000000000088bb00000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000033ee6600000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 0000000000000000000055bbff992200000000000000000000000000000000000000000000000000 +% 000000000000000000000000000000000000000000000000000000000055ff660000000000000000 +% 000000000000000000000000000000000000000000000000000000000000000044ff000000000000 +% 00000000000000000000dd6600000000000000000000000000000000000000000000000000000000 +% 000000000000000000000000000033ee880000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 0000000000000000000000004499ffbb440000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000066ff3300000000000000 +% 000000000000000000000000000000000000000000000000000000000000000044ff000000000000 +% 00000000000000000055ee0000000000000000000000000000000000000000000000000000000000 +% 0000000000000000000000000011cc99000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000002288eecc66000000000000000000000000000000000000000000 +% 0000000000000000000000000000000000000000000000000000000000000066ee33000000000000 +% 000000000000000000000000000000000000000000000000000000000000000044ff000000000000 +% 00000000000000000099990000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000011ccbb00000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 000000000000000000000000000000001188dddd8811000000000000000000000000000000000000 +% 000000000000000000000000000000000000000000000000000000000000000099ee330000000000 +% 000000000000000000000000000000000000000000000000000000000000000044ff000000000000 +% 000000000000000011ff330000000000000000000000000000000000000000000000000000000000 +% 000000000000000000000000aacc1100000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 0000000000000000000000000000000000000066ccee882200000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000099cc1100000000 +% 000000000000000000000000000000000000000000000000000000000000000044bb000000000000 +% 000000000000000077cc000000000000000000000000000000000000000000000000000000000000 +% 000000000000000000000099dd110000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000044bbff99440000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000aacc11000000 +% 000000000000000000000000000000000000000000000000000000000000000044bb000000000000 +% 0000000000000000dd66000000000000000000000000000000000000000000000000000000000000 +% 0000000000000000000088ee33000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000002299ffbb66000000000000000000000000 +% 0000000000000000000000000000000000000000000000000000000000000000000011ccbb000000 +% 000000000000000000000000000000000000000000000000000000000000000044bb000000000000 +% 0000000000000033ff11000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000066ee3300000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 000000000000000000000000000000000000000000000000001188eedd6611000000000000000000 +% 000000000000000000000000000000000000000000000000000000000000000000000011cc990000 +% 000000000000000000000000000000000000000000000000000000000000000044bb000000000000 +% 00000000000000999900000000000000000000000000000000000000000000000000000000000000 +% 000000000000000099ee330000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 0000000000000000000000000000000000000000000000000000000066ddee882200000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000011ee9900 +% 000000000000000000000000000000000000000000000000000000000000000044bb000000000000 +% 00000000000011ee4400000000000000000000000000000000000000000000000000000000000000 +% 0000000000000099ee33000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000055bbff99330000000000 +% 0000000000000000000000000000000000000000000000000000000000000000000000000033ee88 +% 000000000000000000000000000000000000000000000000000000000000000066bb000000000000 +% 00000000000066dd0000000000000000000000000000000000000000000000000000000000000000 +% 00000000001199cc3300000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000003399ffbb44000000 +% 000000000000000000000000000000000000000000000000000000000000000000000000000033ee +% 660000000000000000000000000000000000000000000000000000000000000088bb000000000000 +% 000000000000bb880000000000000000000000000000000000000000000000000000000000000000 +% 0000000011cccc110000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 000000000000000000000000000000000000000000000000000000000000000000002288eedd6600 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000055 +% ff6600000000000000000000000000000000000000000000000000000000000088bb000000000000 +% 000000000022ff220000000000000000000000000000000000000000000000000000000000000000 +% 00000011cccc11000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 0000000000000000000000000000000000000000000000000000000000000000000000001177ddee +% 88110000000000000000000000000000000000000000000000000000000000000000000000000000 +% 66ff33000000000000000000000000000000000000000000000000000000000088bb000000000000 +% 000000000088aa000000000000000000000000000000000000000000000000000000000000000000 +% 000033ccaa1100000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000066 +% bbee9922000000000000000000000000000000000000000000000000000000000000000000000000 +% 0066ee330000000000000000000000000000000000000000000000000000000088bb000000000000 +% 0000000000dd66000000000000000000000000000000000000000000000000000000000000000000 +% 0033ee99000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 0044aaffaa4400000000000000000000000000000000000000000000000000000000000000000000 +% 000099ee3300000000000000000000000000000000000000000000000000000088bb000000000000 +% 0000000055ee00000000000000000000000000000000000000000000000000000000000000000000 +% 33ee9900000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 0000002299eecc660000000000000000000000000000000000000000000000000000000000000000 +% 00000099cc1100000000000000000000000000000000000000000000000000008888000000000000 +% 00000000999900000000000000000000000000000000000000000000000000000000000000000055 +% ee770000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000001188dddd77110000000000000000000000000000000000000000000000000000000000 +% 00000000aacc11000000000000000000000000000000000000000000000000008888000000000022 +% 66110011ff33000000000000000000000000000000000000000000000000000000000000000066ff +% 66000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 000000000000000066ddee8822000000000000000000000000000000000000000000000000000000 +% 0000000011cccc00000000000000000000000000000000000000000000338888c8c8888888220088 +% fff69089cc000000000000000000000000000000000000000000000000000000000000000066ff66 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 0000000000000000000044bbff994400000000000000000000000000000000000000000000000000 +% 000000000011cc9900000000000000000000000000000000000000000077fdffffffffffff660088 +% fffffaffbf4400000000000000000000000000000000000000000000000000000000000088ee3300 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 0000000000000000000000002299ffbb550000000000000000000000000000000000000000000000 +% 00000000000011dd99000000332200000000000000000000000000000022fffffffffffff8110088 +% fffffffffffbe92200000000000000000000000000000000000000000000000000000099ee330000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000001188eedd66110000000000000000000000000000000000000000 +% 0000000000000033ee880066ffeb00000000000000000000000000000000e9ffffffffffa7000088 +% ffffffffffffff55000000000000000000000000000000000000000000000000000099ee33000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 000000000000000000000000000000001166ddee8811000000000000000000000000000000000000 +% 000000000000000033eea3fffffb6600000000000000000000000000000090ffffffffff33000088 +% fffffffffffc800000000000000000000000000000000000000000000000000011cccc1100000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 0000000000000000000000000000000000000055bbff992200000000000000000000000000000000 +% 0000000000000000008fffffffffeb00000000000000000000000000000044faffffffdd00000088 +% fffffffff9a00000000000000000000000000000000000000000000000000011cccc110000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 0000000000000000000000000000000000000000004499ffbb440000000000000000000000000000 +% 000000000000000066fffffffffffb66000000000000000000000000000000f6fffffb6600000088 +% fffffffcbb0000000000000000000000000000000000000000000000000022ccbb11000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000002288eecc66000000000000000000000000 +% 0000000000000055ffffffffffffffeb000000000000000000000000000000a7fffff81100000088 +% fffffad71100000000000000000000000000000000000000222200000033ee990000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 000000000000000000000000000000000000000000000000001188dddd8811000000000000000000 +% 0000000000000022ebfbfffffffffffb66000000000000000000000000000066f9ffa70000000088 +% ffffeb110000000000000000000000000000000000000011f6f6110033ee99000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 0000000000000000000000000000000000000000000000000000000066ccee882200000000002255 +% 00000000000000000066ebfbffffffffeb000000000000000000000000000011ffff330000000088 +% fff5330000000000000000000000000000000000000000b6fafab644ee8800000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000044bbff9944000000ebff +% 800000000000000000000066ebfbfffffb660000000000000022444444668888e6f08888664444a8 +% ff33000000000000000000000000000000000000000055fbfffffcff660000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000002299ffbb5566fbff +% fca0000000000000000000000066ebfbffeb0022448899bbffffffccbbbbbbbb9898bbbbbbbbccff +% ffffbb99884422000000000000000000000000000011f6fffffffff8110000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 000000000000000000000000000000000000000000000000000000000000000000001188eefdffff +% fff9bb11000000000000000000000066f1ffe1ffddbb886644000000000000000000000000000000 +% 00446688bbddffcc88440000000000000000000000b6fafffffffffab60000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000070fdffff +% fffffcd711000000000000000066aaeeeecc70220000000000000000000000000000000000000000 +% 0000000000002266aaeeeeaa660000000000000055fbffffffffffffff5500000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 000000000000000000000000000000000000000000000000000000000000000000000000ebffffff +% fffffffaeb33000000001188dddd8844000000000000000000000000000000000000000000000000 +% 000000000000000000004488dddd881100000011f6fffffffffff9ffc92200000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 000000000000000000000000000000000000000000000000000000000000000000000066ffffffff +% fffffffffff533002299eecc66000000000000000000000000000000000000000000000000000000 +% 0000000000000000000000000066ccee992200b6fbfffffaf6a76611000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 000000000000000000000000000000000000000000000000000000000000000000000022a7cdcdf6 +% fffffffbf2ffffa8ff99440000000000000000000000000000000000000000000000000000000000 +% 0000000000000000000000000000004499ffb0ffffe9904400000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 0000444455a0e8e04400000000000000000000000000000000000000000000000000000000000000 +% 000000000000000000000000000000000044e0e44e00000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 0000000088ff88110000000000000000000000000000000000000000000000000000000000000000 +% 0000000000000000000000000000000000001188ff88000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000099ee3300000000000000000000000000000000000000000000000000000000000000000000 +% 000000000000000000000000000000000000000033ee990000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 000099ee330000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000033ee9900000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 0099ee33000000000000000000000000000000000000000000000000000000000000000000000000 +% 0000000000000000000000000000000000000000000033ee99000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 55ee3300000000000000000000000000000000000000000000000000000000000000000000000000 +% 000000000000000000000000000000000000000000000033ee440000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% dd880000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000088dd0000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000088 +% dd000000000000000000000000002200000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000dd8800000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 000000000000000000000000000000000000000000000000000000000000000000000000000000ee +% 5500000000000000000000bbffff2244448822000000000000000000000000000000000000000000 +% 0000000000000000000000000000000000000000000000000055ee00000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 000000000000000000000000000000000000000000000000000000000000000000000000000022ff +% 11000000000000000000000033ff00000011dd000000000000000000660000006600000000000000 +% 0000000000000000000000000000000000000000000000000011ff22000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 000000000000000000000000000000000000000000000000000000000000000000000000000044dd +% 00000000000000000000000000ff00000011ff000000000000000000dd000000dd00000000000000 +% 0000000000000000000000000000000000000000000000000000dd44000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 000000000000000000000000000000000000000000000000000000000000000000000000000088aa +% 00000000000000000000000000ff0000229988000011bbffbb110088ffff8888ffff880011bbffbb +% 110044cc88ccffbb88eeff880000000000000000000000000000aa88000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 000000000000000000000000000000000000000000000000000000000000000000000000000088aa +% 00000000000000000000000000ffffffffaa110000aa660099aa0000ff000000ff000000aa660099 +% aa0000ff550033ff440033ff0000000000000000000000000000aa88000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 000000000000000000000000000000000000000000000000000000000000000000000000000044dd +% 00000000000000000000000000ff00003399bb0000ff000011ff0000ff000000ff000000ff000011 +% ff0000ff000000ff000000ff0000000000000000000000000000dd44000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 000000000000000000000000000000000000000000000000000000000000000000000000000022ff +% 11000000000000000000000000ff00000000ff0000ff220000ff0000ff000000ff000000ff220000 +% ff0000ff000000ff000000ff0000000000000000000000000011ff22000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 000000000000000000000000000000000000000000000000000000000000000000000000000000ee +% 55000000000000000000000033ff11002288bb0000aa990077990000ff110000ff110000aa990077 +% 990011ff110011ff110011ff1100000000000000000000000055ee00000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000088 +% dd00000000000000000000bbffffffffffaa11000011bbffbb110000aaff7700aaff770011bbffbb +% 1100bbffff44ffffff88ffffbb000000000000000000000000dd8800000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% dd880000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000088dd0000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 55ee3300000000000000000000000000000000000000000000000000000000000000000000000000 +% 000000000000000000000000000000000000000000000033ee440000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 0099ee33000000000000000000000000000000000000000000000000000000000000000000000000 +% 0000000000000000000000000000000000000000000033ee99000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 000099ee330000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000033ee9900000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000099ee3300000000000000000000000000000000000000000000000000000000000000000000 +% 000000000000000000000000000000000000000033ee990000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 0000000088ff88110000000000000000000000000000000000000000000000000000000000000000 +% 0000000000000000000000000000000000001188ff88000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 000000000033ccdd4400000000000000000000000000000000000000000000000000000000000000 +% 000000000000000000000000000000000044ddcc3300000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 0000000000000088ff99440000000000000000000000000000000000000000000000000000000000 +% 0000000000000000000000000000004499ff88000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000002299eecc66000000000000000000000000000000000000000000000000000000 +% 0000000000000000000000000066ccee992200000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 000000000000000000001188dddd8844000000000000000000000000000000000000000000000000 +% 000000000000000000004488dddd8811000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 0000000000000000000000000066aaeeeeaa66220000000000000000000000000000000000000000 +% 0000000000002266aaeeeeaa66000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 000000000000000000000000000000004488ccffddbb886644000000000000000000000000000000 +% 00446688bbddffcc8844000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 0000000000000000000000000000000000000022448899bbffffffccbbbbbbbb8888bbbbbbbbccff +% ffffbb99884422000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000224444446688888888888866444444 +% 22000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000 +%%EndImage +%%EndPreview +save countdictstack mark newpath /showpage {} def /setpagedevice {pop} def +%%EndProlog +%%Page 1 1 +save +/DotDict 200 dict def +DotDict begin + +/setupLatin1 { +mark +/EncodingVector 256 array def + EncodingVector 0 + +ISOLatin1Encoding 0 255 getinterval putinterval + +EncodingVector + dup 306 /AE + dup 301 /Aacute + dup 302 /Acircumflex + dup 304 /Adieresis + dup 300 /Agrave + dup 305 /Aring + dup 303 /Atilde + dup 307 /Ccedilla + dup 311 /Eacute + dup 312 /Ecircumflex + dup 313 /Edieresis + dup 310 /Egrave + dup 315 /Iacute + dup 316 /Icircumflex + dup 317 /Idieresis + dup 314 /Igrave + dup 334 /Udieresis + dup 335 /Yacute + dup 376 /thorn + dup 337 /germandbls + dup 341 /aacute + dup 342 /acircumflex + dup 344 /adieresis + dup 346 /ae + dup 340 /agrave + dup 345 /aring + dup 347 /ccedilla + dup 351 /eacute + dup 352 /ecircumflex + dup 353 /edieresis + dup 350 /egrave + dup 355 /iacute + dup 356 /icircumflex + dup 357 /idieresis + dup 354 /igrave + dup 360 /dcroat + dup 361 /ntilde + dup 363 /oacute + dup 364 /ocircumflex + dup 366 /odieresis + dup 362 /ograve + dup 365 /otilde + dup 370 /oslash + dup 372 /uacute + dup 373 /ucircumflex + dup 374 /udieresis + dup 371 /ugrave + dup 375 /yacute + dup 377 /ydieresis + +% Set up ISO Latin 1 character encoding +/starnetISO { + dup dup findfont dup length dict begin + { 1 index /FID ne { def }{ pop pop } ifelse + } forall + /Encoding EncodingVector def + currentdict end definefont +} def +/Times-Roman starnetISO def +/Times-Italic starnetISO def +/Times-Bold starnetISO def +/Times-BoldItalic starnetISO def +/Helvetica starnetISO def +/Helvetica-Oblique starnetISO def +/Helvetica-Bold starnetISO def +/Helvetica-BoldOblique starnetISO def +/Courier starnetISO def +/Courier-Oblique starnetISO def +/Courier-Bold starnetISO def +/Courier-BoldOblique starnetISO def +cleartomark +} bind def + +/coord-font-family /Times-Roman def +/default-font-family /Times-Roman def +/coordfont coord-font-family findfont 8 scalefont def + +/InvScaleFactor 1.0 def +/set_scale { + dup 1 exch div /InvScaleFactor exch def + dup scale +} bind def + +% styles +/solid { [] 0 setdash } bind def +/dashed { [9 InvScaleFactor mul dup ] 0 setdash } bind def +/dotted { [1 InvScaleFactor mul 6 InvScaleFactor mul] 0 setdash } bind def +/invis {/fill {newpath} def /stroke {newpath} def /show {pop newpath} def} bind def +/bold { 2 setlinewidth } bind def +/filled { } bind def +/unfilled { } bind def +/rounded { } bind def +/diagonals { } bind def + +% hooks for setting color +/nodecolor { sethsbcolor } bind def +/edgecolor { sethsbcolor } bind def +/graphcolor { sethsbcolor } bind def +/nopcolor {pop pop pop} bind def + +/beginpage { % i j npages + /npages exch def + /j exch def + /i exch def + /str 10 string def + npages 1 gt { + gsave + coordfont setfont + 0 0 moveto + (\() show i str cvs show (,) show j str cvs show (\)) show + grestore + } if +} bind def + +/set_font { + findfont exch + scalefont setfont +} def + +% draw aligned label in bounding box aligned to current point +/alignedtext { % width adj text + /text exch def + /adj exch def + /width exch def + gsave + width 0 gt { + text stringwidth pop adj mul 0 rmoveto + } if + [] 0 setdash + text show + grestore +} def + +/boxprim { % xcorner ycorner xsize ysize + 4 2 roll + moveto + 2 copy + exch 0 rlineto + 0 exch rlineto + pop neg 0 rlineto + closepath +} bind def + +/ellipse_path { + /ry exch def + /rx exch def + /y exch def + /x exch def + matrix currentmatrix + newpath + x y translate + rx ry scale + 0 0 1 0 360 arc + setmatrix +} bind def + +/endpage { showpage } bind def +/showpage { } def + +/layercolorseq + [ % layer color sequence - darkest to lightest + [0 0 0] + [.2 .8 .8] + [.4 .8 .8] + [.6 .8 .8] + [.8 .8 .8] + ] +def + +/layerlen layercolorseq length def + +/setlayer {/maxlayer exch def /curlayer exch def + layercolorseq curlayer 1 sub layerlen mod get + aload pop sethsbcolor + /nodecolor {nopcolor} def + /edgecolor {nopcolor} def + /graphcolor {nopcolor} def +} bind def + +/onlayer { curlayer ne {invis} if } def + +/onlayers { + /myupper exch def + /mylower exch def + curlayer mylower lt + curlayer myupper gt + or + {invis} if +} def + +/curlayer 0 def + +14 default-font-family set_font +1 setmiterlimit +% /arrowlength 10 def +% /arrowwidth 5 def + +% make sure pdfmark is harmless for PS-interpreters other than Distiller +/pdfmark where {pop} {userdict /pdfmark /cleartomark load put} ifelse +% make '<<' and '>>' safe on PS Level 1 devices +/languagelevel where {pop languagelevel}{1} ifelse +2 lt { + userdict (<<) cvn ([) cvn load put + userdict (>>) cvn ([) cvn load put +} if + +gsave +35 35 431 326 boxprim clip newpath +36 36 translate +0 0 1 beginpage +0 0 translate 0 rotate +0.000 0.000 0.000 graphcolor +14.00 /Times-Roman set_font + +% Top +gsave 10 dict begin +236 306 27 18 ellipse_path +stroke +gsave 10 dict begin +225 301 moveto +(Top) +[7.44 6.96 6.96] +xshow +end grestore +end grestore + +% NullableStr +gsave 10 dict begin +132 234 45 18 ellipse_path +stroke +gsave 10 dict begin +99 229 moveto +(NullableStr) +[9.84 6.96 3.84 3.84 6.24 6.96 3.84 6.24 7.44 3.84 4.56] +xshow +end grestore +end grestore + +% Top -> NullableStr +newpath 217 293 moveto +202 283 181 268 163 256 curveto +stroke +gsave 10 dict begin +solid +1 setlinewidth +0.000 0.000 0.000 edgecolor +newpath 165 253 moveto +155 250 lineto +161 259 lineto +closepath +fill +0.000 0.000 0.000 edgecolor +newpath 165 253 moveto +155 250 lineto +161 259 lineto +closepath +stroke +end grestore + +% Int +gsave 10 dict begin +42 234 27 18 ellipse_path +stroke +gsave 10 dict begin +34 229 moveto +(Int) +[4.56 6.96 3.84] +xshow +end grestore +end grestore + +% Top -> Int +newpath 211 299 moveto +180 289 124 271 78 252 curveto +76 251 74 250 72 249 curveto +stroke +gsave 10 dict begin +solid +1 setlinewidth +0.000 0.000 0.000 edgecolor +newpath 74 246 moveto +63 245 lineto +71 252 lineto +closepath +fill +0.000 0.000 0.000 edgecolor +newpath 74 246 moveto +63 245 lineto +71 252 lineto +closepath +stroke +end grestore + +% *instances* +gsave 10 dict begin +newpath 277 252 moveto +195 252 lineto +195 216 lineto +277 216 lineto +closepath +stroke +gsave 10 dict begin +203 229 moveto +(*instances*) +[6.96 3.84 6.96 5.28 4.08 6.24 6.96 6.24 6.24 5.52 6.96] +xshow +end grestore +end grestore + +% Top -> *instances* +newpath 236 288 moveto +236 280 236 271 236 262 curveto +stroke +gsave 10 dict begin +solid +1 setlinewidth +0.000 0.000 0.000 edgecolor +newpath 240 262 moveto +236 252 lineto +233 262 lineto +closepath +fill +0.000 0.000 0.000 edgecolor +newpath 240 262 moveto +236 252 lineto +233 262 lineto +closepath +stroke +end grestore + +% *PBCs* +gsave 10 dict begin +newpath 429 252 moveto +367 252 lineto +367 216 lineto +429 216 lineto +closepath +stroke +gsave 10 dict begin +375 229 moveto +(*PBCs*) +[6.96 7.68 9.36 9.36 5.52 6.96] +xshow +end grestore +end grestore + +% Top -> *PBCs* +newpath 259 296 moveto +281 286 317 269 358 252 curveto +stroke +gsave 10 dict begin +solid +1 setlinewidth +0.000 0.000 0.000 edgecolor +newpath 359 255 moveto +367 248 lineto +356 249 lineto +closepath +fill +0.000 0.000 0.000 edgecolor +newpath 359 255 moveto +367 248 lineto +356 249 lineto +closepath +stroke +end grestore + +% *lists* +gsave 10 dict begin +newpath 349 252 moveto +295 252 lineto +295 216 lineto +349 216 lineto +closepath +stroke +gsave 10 dict begin +303 229 moveto +(*lists*) +[6.96 3.84 3.84 5.28 3.84 5.52 6.96] +xshow +end grestore +end grestore + +% Top -> *lists* +newpath 253 292 moveto +265 283 280 270 292 259 curveto +stroke +gsave 10 dict begin +solid +1 setlinewidth +0.000 0.000 0.000 edgecolor +newpath 295 261 moveto +300 252 lineto +290 256 lineto +closepath +fill +0.000 0.000 0.000 edgecolor +newpath 295 261 moveto +300 252 lineto +290 256 lineto +closepath +stroke +end grestore + +% Str +gsave 10 dict begin +159 162 27 18 ellipse_path +stroke +gsave 10 dict begin +151 157 moveto +(Str) +[7.44 3.84 4.56] +xshow +end grestore +end grestore + +% NullableStr -> Str +newpath 139 216 moveto +142 208 145 198 149 189 curveto +stroke +gsave 10 dict begin +solid +1 setlinewidth +0.000 0.000 0.000 edgecolor +newpath 152 191 moveto +153 180 lineto +146 188 lineto +closepath +fill +0.000 0.000 0.000 edgecolor +newpath 152 191 moveto +153 180 lineto +146 188 lineto +closepath +stroke +end grestore + +% None +gsave 10 dict begin +289 162 29 18 ellipse_path +stroke +gsave 10 dict begin +273 157 moveto +(None) +[9.84 6.96 6.96 6.24] +xshow +end grestore +end grestore + +% NullableStr -> None +newpath 162 220 moveto +189 207 228 189 256 177 curveto +stroke +gsave 10 dict begin +solid +1 setlinewidth +0.000 0.000 0.000 edgecolor +newpath 257 180 moveto +265 173 lineto +254 174 lineto +closepath +fill +0.000 0.000 0.000 edgecolor +newpath 257 180 moveto +265 173 lineto +254 174 lineto +closepath +stroke +end grestore + +% Char +gsave 10 dict begin +165 90 27 18 ellipse_path +stroke +gsave 10 dict begin +151 85 moveto +(Char) +[9.36 6.96 6.24 4.56] +xshow +end grestore +end grestore + +% Str -> Char +newpath 161 144 moveto +162 136 162 127 163 118 curveto +stroke +gsave 10 dict begin +solid +1 setlinewidth +0.000 0.000 0.000 edgecolor +newpath 167 118 moveto +163 108 lineto +160 118 lineto +closepath +fill +0.000 0.000 0.000 edgecolor +newpath 167 118 moveto +163 108 lineto +160 118 lineto +closepath +stroke +end grestore + +% Bottom +gsave 10 dict begin +232 18 34 18 ellipse_path +stroke +gsave 10 dict begin +210 13 moveto +(Bottom) +[9.36 6.72 3.84 3.84 6.96 10.8] +xshow +end grestore +end grestore + +% Char -> Bottom +newpath 180 74 moveto +189 64 200 52 210 41 curveto +stroke +gsave 10 dict begin +solid +1 setlinewidth +0.000 0.000 0.000 edgecolor +newpath 212 44 moveto +217 34 lineto +207 39 lineto +closepath +fill +0.000 0.000 0.000 edgecolor +newpath 212 44 moveto +217 34 lineto +207 39 lineto +closepath +stroke +end grestore + +% NonNegInt +gsave 10 dict begin +45 162 45 18 ellipse_path +stroke +gsave 10 dict begin +13 157 moveto +(NonNegInt) +[9.84 6.96 6.96 9.84 6.24 6.96 4.56 6.96 3.84] +xshow +end grestore +end grestore + +% Int -> NonNegInt +newpath 43 216 moveto +44 208 44 199 44 190 curveto +stroke +gsave 10 dict begin +solid +1 setlinewidth +0.000 0.000 0.000 edgecolor +newpath 48 190 moveto +44 180 lineto +41 190 lineto +closepath +fill +0.000 0.000 0.000 edgecolor +newpath 48 190 moveto +44 180 lineto +41 190 lineto +closepath +stroke +end grestore + +% Bool +gsave 10 dict begin +72 90 27 18 ellipse_path +stroke +gsave 10 dict begin +57 85 moveto +(Bool) +[9.36 6.96 6.96 3.84] +xshow +end grestore +end grestore + +% NonNegInt -> Bool +newpath 52 144 moveto +55 136 58 126 62 117 curveto +stroke +gsave 10 dict begin +solid +1 setlinewidth +0.000 0.000 0.000 edgecolor +newpath 65 119 moveto +66 108 lineto +59 116 lineto +closepath +fill +0.000 0.000 0.000 edgecolor +newpath 65 119 moveto +66 108 lineto +59 116 lineto +closepath +stroke +end grestore + +% Bool -> Bottom +newpath 95 80 moveto +121 68 166 48 197 34 curveto +stroke +gsave 10 dict begin +solid +1 setlinewidth +0.000 0.000 0.000 edgecolor +newpath 198 37 moveto +206 30 lineto +195 31 lineto +closepath +fill +0.000 0.000 0.000 edgecolor +newpath 198 37 moveto +206 30 lineto +195 31 lineto +closepath +stroke +end grestore + +% *instances* -> Bottom +newpath 236 216 moveto +235 178 233 91 232 46 curveto +stroke +gsave 10 dict begin +solid +1 setlinewidth +0.000 0.000 0.000 edgecolor +newpath 236 46 moveto +232 36 lineto +229 46 lineto +closepath +fill +0.000 0.000 0.000 edgecolor +newpath 236 46 moveto +232 36 lineto +229 46 lineto +closepath +stroke +end grestore + +% *instances* -> None +newpath 249 216 moveto +256 208 264 197 271 187 curveto +stroke +gsave 10 dict begin +solid +1 setlinewidth +0.000 0.000 0.000 edgecolor +newpath 274 189 moveto +277 179 lineto +268 185 lineto +closepath +fill +0.000 0.000 0.000 edgecolor +newpath 274 189 moveto +277 179 lineto +268 185 lineto +closepath +stroke +end grestore + +% None -> Bottom +newpath 282 144 moveto +272 120 254 75 243 46 curveto +stroke +gsave 10 dict begin +solid +1 setlinewidth +0.000 0.000 0.000 edgecolor +newpath 246 44 moveto +239 36 lineto +239 47 lineto +closepath +fill +0.000 0.000 0.000 edgecolor +newpath 246 44 moveto +239 36 lineto +239 47 lineto +closepath +stroke +end grestore + +% *PBCs* -> Bottom +newpath 391 216 moveto +374 179 331 89 266 36 curveto +stroke +gsave 10 dict begin +solid +1 setlinewidth +0.000 0.000 0.000 edgecolor +newpath 268 33 moveto +258 30 lineto +264 39 lineto +closepath +fill +0.000 0.000 0.000 edgecolor +newpath 268 33 moveto +258 30 lineto +264 39 lineto +closepath +stroke +end grestore + +% *PBCs* -> None +newpath 370 216 moveto +354 206 334 192 318 181 curveto +stroke +gsave 10 dict begin +solid +1 setlinewidth +0.000 0.000 0.000 edgecolor +newpath 319 178 moveto +309 175 lineto +315 183 lineto +closepath +fill +0.000 0.000 0.000 edgecolor +newpath 319 178 moveto +309 175 lineto +315 183 lineto +closepath +stroke +end grestore + +% *lists* -> None +newpath 314 216 moveto +310 208 306 198 301 189 curveto +stroke +gsave 10 dict begin +solid +1 setlinewidth +0.000 0.000 0.000 edgecolor +newpath 304 188 moveto +297 180 lineto +298 191 lineto +closepath +fill +0.000 0.000 0.000 edgecolor +newpath 304 188 moveto +297 180 lineto +298 191 lineto +closepath +stroke +end grestore +endpage +showpage +grestore +end +restore +%%Trailer +cleartomark countdictstack exch sub { end } repeat restore +%%EOF Added: pypy/extradoc/talk/dls2006/image/lattice2.eps ============================================================================== --- (empty file) +++ pypy/extradoc/talk/dls2006/image/lattice2.eps Wed May 31 14:35:47 2006 @@ -0,0 +1,3891 @@ +%!PS-Adobe-2.0 EPSF-1.2 +%%Title: lattice2 +%%Creator: dot version 2.2 (Tue Mar 22 18:02:44 UTC 2005) +%%CreationDate: 2006-05-31 14:20 lattice2.ps +%%For: (carlson) Carl Friedrich Bolz +%%Pages: 1 +%%DocumentFonts: +%%BoundingBox: 35 35 419 361 +%%EndComments + +%%BeginProlog +%%BeginPreview: 384 326 8 3260 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000114466888866441100000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000033448888bbccffffeebbaaaabbeeffffccbb88 +% 88443300000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 0000000000000000000000000000000000000066bbffccbb88884444000000000000000044448888 +% bbccffbb660000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 000000000000000000000000000000001166ddee8811000000000000000000000000000000000000 +% 00001188eedd66110000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000002288eedd66000000000000000000000000000000000000000000 +% 000000000066ddee8822000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 0000000000000000000000002299ffbb550000000000000000000000000000000000000000000000 +% 0000000000000055bbff992200000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 000000000000000000000033eeaa3300000000000000000000000000000000000000000000000000 +% 00000000000000000033aaee33000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 0000000000000000000033ee88000000000000000000000000000000000000000000000000000000 +% 000000000000000000000099ee330000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000033ee6600000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000066ee3300000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 000000000000000033ee660000000000000000000000000000000000000000000000000000000000 +% 0000000000000000000000000066ee33000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 0000000000000033ee66000000000000000000000000000000000000000000000000000000000000 +% 000000000000000000000000000066ee330000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000033ee6600000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000066ee3300000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000099880000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000889900000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 000000000000ee550000000000000000000000000000000000000000000000000000000000000000 +% 0000000000000000000000000000000055ee00000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 000000000044ee000000000000000000000000000000000000000000000000000000000000000000 +% 0000000000000000000000000000000000ee44000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 000000000088990000000000000000000000000000bbffffffffffffff4400000000000000000000 +% 0000000000000000000000000000000000aa88000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 0000000000dd66000000000000000000000000000099220000ff0000664400000000000000000000 +% 000000000000000000000000000000000066dd000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 0000000022ff11000000000000000000000000000000000000ff0000000000000000000000000000 +% 000000000000000000000000000000000011ff220000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 0000000077bb00000000000000000000000000000000000000ff00000011bbffbb110044dd99ffdd +% 330000000000000000000000000000000000bb770000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 0000000077bb00000000000000000000000000000000000000ff000000aa660099aa0000ff440088 +% cc0000000000000000000000000000000000bb770000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 0000000022ff11000000000000000000000000000000000000ff000000ff000011ff0000ff000011 +% ff0000000000000000000000000000000011ff220000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 0000000000dd66000000000000000000000000000000000000ff000000ff220000ff0000ff000011 +% ee0000000000000000000000000000000066dd000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000008899000000000000000000000000000000000033ff220000aa990077990000ff440088 +% 8800000000000000000000000000000000aa88000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 000000000044ee00000000000000000000000000000000bbffffff440011bbffbb110000ffddff99 +% 1100000000000000000000000000000000ee44000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 000000000000ee5500000000000000000000000000000000000000000000000000000000ff000000 +% 0000000000000000000000000000000055ee00000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 000000000000998800000000000000000000000000000000000000000000000000000011ff110000 +% 00000000000000000000000000000000889900000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000033ee660000000000000000000000000000000000000000000000000000ffffff8800 +% 00000000000000000000000000000066ee3300000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 0000000000000033ee66000000000000000000000000000000000000000000000000000000000000 +% 000000000000000000000000000066ee330000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 000000000000000033ee660000000000000000000000000000000000000000000000000000000000 +% 0000000000000000000000000066ee33000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000033ee6600000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000066ee3300000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 0000000000000000000033ee88000000000000000000000000000000000000000000000000000000 +% 000000000000000000000099ee330000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 000000000000000000000033eeaa3300000000000000000000000000000000000000000000000000 +% 00000000000000000033aaee33000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 0000000000000000000000002299ffbb550000000000000000000000000000000000000000000000 +% 0000000000000055bbff992200000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000002288eedd66000000000000000000000000000000000000000000 +% 000000000066ddee8822000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 000000000000000000000000000000001166ddee8811000000000000000000000000000000000000 +% 00001188eedd66110000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 0000000000000000000000000000000000000066bbffccbb88884444000000000000000044448888 +% bbccffbb660000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000033448888bbccffffeebbaaaabbeeffffccbb88 +% 88443300000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000114466c8c866441100000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000888800000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000888800000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000888800000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000888800000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000888800000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000888800000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000888800000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000888800000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000888800000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000888800000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000888800000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000888800000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000888800000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000888800000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000888800000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000888800000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000888800000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000888800000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000888800000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000888800000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000888800000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000888800000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000888800000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000888800000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000338888c8c888888822000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 0000000000000000000000000000000000000000000000000000000077fdffffffffffff66000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 0000000000000000000000000000000000000000000000000000000022fffffffffffff811000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 0000000000000000000000000000000000000000000000000000000000e9ffffffffffa700000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 000000000000000000000000000000000000000000000000000000000090ffffffffff3300000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 000000000000000000000000000000000000000000000000000000000044faffffffdd0000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 000000000000000000000000000000000000000000000000000000000000f6fffffb660000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 000000000000000000000000000000000000000000000000000000000000a7fffff8110000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000066f9ffa7000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000011ffff33000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000004444444444444455888888888888e6f088888888888855 +% 44444444444433000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 0000000000444455888888bbbbbbffffffffffffccbbbbbbbbbbbbbbbbaa88989888aabbbbbbbbbb +% bbbbbbccffffffffffffbbbbbb888888554444000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000114466 +% 88aabbeeffffddbbbb99888877444433000000000000000000000000000000000000000000000000 +% 000000000000000033444477888899bbbbddffffeebbaa8866441100000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000225588aabbffffffbb +% aa886644110000000000000000000000000000000000000000000000000000000000000000000000 +% 0000000000000000000000000000000000000011446688aabbffffffbbaa88551100000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 0000000000000000000000000000000000000000000000000000004477aaddffdd99885544110000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000001144558899ddffddaa7744000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000226688ccffeebb8844110000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 0000000000000000000000000000000000000000000000000000000000000000114488bbeeffcc88 +% 66220000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 000000000000000000000000000000000000002277ccffcc88662200000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000336688 +% ccffcc77220000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 000000000000000000000000000000003388ddffaa77220000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 002277aaffdd88330000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 000000000000000000000000002288ddffaa66110000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 000000001166aaffdd88220000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000002299ffbb55000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 000000000000000055bbff9922000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 0000000000000000002299ff99440000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 000000000000000000004499ff992200000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 0000000000000011aaff992200000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 0000000000000000000000002299ffaa110000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000033eeaa22000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 000000000000000000000000000022aaee3300000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 000000000066ee880000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 0000000000000000000000000000000088ee66000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 0000000077ff66000000000000000000000000000000000000000000000000001166000011660000 +% 00000000000011660000000000116600000000000000000000000000000000000000000000000000 +% 00000000000011110000000000000011660000000000000000000000000000000000000000000000 +% 000033000000000000000000000000000066ff770000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000044ee33000000000000000000bbffee11000088ffffff0000000000000033ff000033ff0000 +% 00000000000055ff000000000033ff0000000000000000bbffffff88000000000000000000000000 +% 00000000003366000000000000000055ff00000000000099dd000000000000000000000000000000 +% 00000077110000000000000000000000000033ee4400000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000099990000000000000000000033ffddcc11000033ff330000000000000000ff000000ff0000 +% 00000000000000ff000000000000ff00000000000000000033ff2200000000000000000000000000 +% 00660000008800000000000000000000ff0000000000000000000000000000000000000000000066 +% 00000000880000000000000000000000000000999900000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 000011ff330000000000000000000000ff33ee99000000ff000000000000000000ff000000ff0000 +% 00000000000000ff000000000000ff00000000000000000000ff0000000000000000000000000000 +% 00dd0000665500000000000000000000ff00000000000000550000000000000000000000000000dd +% 0000000077440000000000000000000000000033ff11000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 000077cc000000000000000000000000ff0033ee880000ff00bbff0044ffff0000ff000000ff0000 +% 88eeff88000000ff99ffdd330000ff00000066ddffbb110000ff0044cc99ddff88000088ffff6600 +% 88ffff88bb2200000011bbffbb110000ff99ffdd33002288ff000066ddffbb111188eeffcc3388ff +% ff88000033aa0000000000000000000000000000cc77000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 000077cc000000000000000000000000ff000055ff6600ff0011ff000011ff0000ff000000ff0000 +% aa0033ff000000ff440099bb0000ff000044ffffffff880000ff0000ff660033ff0000ff22114400 +% 00ff0000ff00000000aa660099aa0000ff440099bb000000ff0044ffffffff8899991100884400ff +% 0000000000ee0000000000000000000000000000cc77000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 000011ff330000000000000000000000ff00000066ee33ff0000ff000000ff0000ff000000ff0000 +% 001166ff000000ff000011ff0000ff00008877000000000000ff0000ff000000ff00005577110000 +% 00ff0000ff00000000ff000011ff0000ff000011ff000000ff00887700000000ee110000000000ff +% 0000000000ff0000000000000000000000000033ff11000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000099990000000000000000000000ff0000000088eeff0000ff000000ff0000ff000000ff0000 +% 333300ff000000ff000000ee0000ff0000aa99000000220000ff0000ff000000ff00001111776600 +% 00ff0000ff00000000ff220000ff0000ff000000ee000000ff00aa9900000022ff220000001100ff +% 0000000000ff00000000000000000000000000999900000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000044ee3300000000000000000011ff440000000099ff0000ff330055ff0011ff220011ff2200 +% ee3344ff110000ff220088880011ff220066ff550044660022ff2211ff110011ff1100990033ff00 +% 00ff1100bb22000000aa990077990000ff22008888000000ff0066ff55004466aacc2200446600ff +% 1100000033aa00000000000000000000000033ee4400000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 0000000077ff660000000000000000bbffff880000000099000088ffdd77cc44bbffff88bbffff88 +% aaee88dddd220099ffff880000bbffff880088ffee8800bbffffffe0ffff44ffffbb00ddffee7700 +% 00aaff77666600000011bbffbb11000099ffff8800000000ff000088ffee880011aaffee880000aa +% ff7700006666000000000000000000000066ff770000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 000000000066ee880000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 000000000088000000000000000000000000000000000000ff000000000000000000000000000000 +% 0000000099000000000000000000000088ee66000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000033eeaa22000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 000000000022550000000000000000000000000000331100bb000000000000000000000000000000 +% 000000771100000000000000000022aaee3300000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 0000000000000011aaff992200000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 000000000000221100000000000000000000000000cccc8833000000000000000000000000000000 +% 0000330000000000000000002299ffaa110000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 0000000000000000002299ff99440000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 000000000000000000004499ff992200000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000002299ffbb55000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 000000000000000055bbff9922000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 000000000000000000000000002288ddffaa66110000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 000000001166aaffdd88220000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 000000000000000000000000000000003388ddffaa77220000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 002277aaffdd88330000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 000000000000000000000000000000000000002277ccffcc88662200000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000336688 +% ccffcc77220000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000226688ccffeebb8844110000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 0000000000000000000000000000000000000000000000000000000000000000114488bbeeffcc88 +% 66220000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 0000000000000000000000000000000000000000000000000000004477aaddffdd99885544110000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000001144558899ddffddaa7744000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000225588aabbffffffbb +% aa886644110000000000000000000000000000000000000000000000000000000000000000000000 +% 0000000000000000000000000000000000000011446688aabbffffffbbaa88551100000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000114466 +% 88aad7eeffffddbbbb99888877444433000000000000000000000000000000000000000000000000 +% 000000000000000033444477888899bbbbddffffeed7aa8866441100000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 44ccee2200444455888888bbbbbbffffffffffffccbbbbbbbbbbbbbbbbaa88888888aabbbbbbbbbb +% bbbbbbccffffffffffffbbbbbb8888884444440022eecc4400000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 000000000000000000000000000000000000000000000000000000000000000000000000000022bb +% ee881100000000000000000000000000003344444444444455888888888888c8c888888888888855 +% 4444444444443300000000000000000000000000001188eebb220000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 0000000000000000000000000000000000000000000000000000000000000000000000001199ff99 +% 22000000000000000000000000000000000000000000000000000000000000888800000000000000 +% 00000000000000000000000000000000000000000000002299ff9911000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 000000000000000000000000000000000000000000000000000000000000000000001188eebb3300 +% 00000000000000000000000000000000000000000000000000000000000000888800000000000000 +% 0000000000000000000000000000000000000000000000000033bbee881100000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000066dddd44000000 +% 00000000000000000000000000000000000000000000000000000000000000888800000000000000 +% 00000000000000000000000000000000000000000000000000000044dddd66000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 0000000000000000000000000000000000000000000000000000000000000044ccee770000000000 +% 00000000000000000000000000000000000000000000000000000000000000888800000000000000 +% 000000000000000000000000000000000000000000000000000000000077eebb4400000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 000000000000000000000000000000000000000000000000000000000022aaff8811000000000000 +% 00000000000000000000000000000000000000000000000000000000000000888800000000000000 +% 0000000000000000000000000000000000000000000000000000000000001188ffaa220000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 0000000000000000000000000000000000000000000000000000001188ff99220000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000888800000000000000 +% 00000000000000000000000000000000000000000000000000000000000000002299ff8811000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 000000000000000000000000000000000000000000000000000088eebb4400000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000888800000000000000 +% 0000000000000000000000000000000000000000000000000000000000000000000044bbee770000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000055dddd55000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000888800000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000055dddd55 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 0000000000000000000000000000000000000000000033bbee880000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000888800000000000000 +% 000000000000000000000000000000000000000000000000000000000000000000000000000088ee +% bb330000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000002299ff9911000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000888800000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000011 +% 99ff9922000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 0000000000000000000000000000000000001188eebb220000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000888800000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 0022bbee881100000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 000000000000000000000000000000000066dddd4400000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000888800000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000044dddd66000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000044ccee66000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000888800000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 000000000066eecc4400000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 0000000000000000000000000022aaff881100000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000888800000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 0000000000001188ffaa220000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000001188ff9922000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000888800000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000002299ff8811000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 0000000000000000000077eebb440000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000888800000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 0000000000000000000044bbee660000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 000000000000000044dddd6600000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000888800000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000066dddd44000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000022bbee88110000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000888800000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 000000000000000000000000001188eebb2200000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 000000001188ff992200000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000888800000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 0000000000000000000000000000002299ff88110000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000077eebb44000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000888800000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 000000000000000000000000000000000044bbee7700000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 0044dddd660000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000888800000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 0000000000000000000000000000000000000066dddd440000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000022 +% bbee8811000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000888800000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000001188eebb22000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 000000000000000000000000000000000000000000000000000000000000000000000000001188ff +% 99220000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000888800000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 000000000000000000000000000000000000000000002299ff881100000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000077eebb33 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000888800000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000033bbee77000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 0000000000000000000000000000000000000000000000000000000000000000000044dddd550000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000338888c8c888888822000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 000000000000000000000000000000000000000000000000000055dddd4400000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 000000000000000000000000000000000000000000000000000000000000000022bbee8800000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 0000000000000000000000000000000000000000000000000000000077fdffffffffffff66000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 0000000000000000000000000000000000000000000000000000001188eebb220000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 0000000000000000000000000000000000000000000000000000000000001188ff99220000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 0000000000000000000000000000000000000000000000000000000022fffffffffffff811000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000002299ff8811000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 000000000000000000000000000000000000000000000000000000000077eebb4400000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 0000000000000000000000000000000000000000000000000000000000e9ffffffffffa700000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 0000000000000000000000000000000000000000000000000000000000000044bbee770000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000003322000000000044ccdd66000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 000000000000000000000000000000000000000000000000000000000090ffffffffff3300000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000066ddcc44000000 +% 00002244000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 0000000000000000000000000000000000000033ffeb00000022aaee881100000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 000000000000000000000000000000000000000000000000000000000044faffffffdd0000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 000000000000000000000000000000000000000000000000000000000000000000001188eeaa2200 +% 0000ebff330000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000033f5fffb661188ffaa22000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 000000000000000000000000000000000000000000000000000000000000f6fffffb660000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000022aaff88 +% 1166fbfff53300000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 000000000000000000000000000000000011ebffffffeeeecc440000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 000000000000000000000000000000000000000000000000000000000000a7fffff8110000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 000000000000000000000000000000000000000000000000000000000000000000000000000044cc +% eeeeffffffeb11000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 0000000000000000000000000000000011d7fafffffffba300000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000066f9ffa7000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% a3fbfffffffad7110000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000bbfcffffffffffeb00000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000011ffff33000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% ebfffffffffffcbb0000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000003344444444444477888888888888888888888888774444444444443300 +% 000000000000000000000000000000a0f9ffffffffffffff66000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000334444444477888888e6f088888877444444 +% 44330000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000066 +% fffffffffffffff9a000000000000000000000000000000000334444444444447788888888888888 +% 88888888887744444444444433000000000000000000000000000000000000000000000000000000 +% 000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000011 +% 444466888899bbbbeeffffffffffbbbbbbbbbbbbbbbbaa88888888aabbbbbbbbbbbbbbbbffffffff +% ffeebbbb9988886644441100000080fcfffffffff6ffebbb22000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 000000000000000000000000000033447788aabbeeffffffccbbbbbbbbbb99989899bbbbbbbbbbcc +% ffffffeebbaa88774433000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000022 +% bbebfff6fffffffffc8000000011444466888899bbbbeeffffffffffbbbbbbbbbbbbbbbbaa888888 +% 88aabbbbbbbbbbbbbbbbffffffffffeebbbb99888866444411000000000000000000000000000000 +% 000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000033448899bbeeff +% ffccbbbb888888444444000000000000000000000000000000000000000000000000000000000000 +% 444444888888bbbbccffffeebbb4ffffffebbb884411000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 000000000000000000115588bbffffddbb9988664422000000000000000000000000000000000000 +% 00002244668899bbddffffbb88551100000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 0000114488bbebffffffb4bbeeffffccbbbb88888844444400000000000000000000000000000000 +% 0000000000000000000000000000444444888888bbbbccffffeebb99884433000000000000000000 +% 000000000000000000000000000000000000000000000000 +% 000000000000000000000000000000000000000000000000000000226688bbccffffccbb88664411 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 0000000000000000000011446690e0daffffccbb8866220000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000002277aaddffdd9977440000000000000000000000000000000000000000000000000000 +% 00000000000000000000447799ddffddaa7722000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00226688bbccffffdae0906644110000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000011446688bbccffffccbb886622000000 +% 000000000000000000000000000000000000000000000000 +% 0000000000000000000000000000000000000000000000337799ddffcc9988443300000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 000000000000000000000000000000000033448899ccffdd99773300000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00002277ccffcc885511000000000000000000000000000000000000000000000000000000000000 +% 0000000000000000000000000000115588ccffcc7722000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000337799 +% ddffcc99884433000000000000000000000000000000000000000000000000000000000000000000 +% 0000000000000000000000000000000000000000000000000000000000000033448899ccffdd9977 +% 330000000000000000000000000000000000000000000000 +% 000000000000000000000000000000000000004488bbeeffbb885511000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000115588bbffeebb8844000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000011 +% 77ccffcc772200000000000000000000000000000000000000000000000000000000000000000000 +% 0000000000000000000000000000000000002277ccffcc7711000000000000000000000000000000 +% 0000000000000000000000000000000000000000000000000000000000000000004488bbeeffbb88 +% 55110000000000000000000000000000000000000000000000000000000000000000000000000000 +% 000000000000000000000000000000000000000000000000000000000000000000000000115588bb +% ffeebb884400000000000000000000000000000000000000 +% 000000000000000000000000000000003388ddeeaa77440000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 0000000000000000000000000000000000000000000000000000004477aaeedd8833000000000000 +% 000000000000000000000000000000000000000000000000000000000000000000000000002288ee +% cc772200000000000000000000000000000000000000000000000000000000000000000000000000 +% 0000000000000000000000000000000000000000002277ccee882200000000000000000000000000 +% 0000000000000000000000000000000000000000000000000000000000003388ddeeaa7744000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 004477aaeedd883300000000000000000000000000000000 +% 000000000000000000000000003388ddee9955000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 000000000000000000000000000000000000000000000000000000000000005599eedd8833000000 +% 00000000000000000000000000000000000000000000000000000000000000000000002299ffbb44 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000044bbff99220000000000000000000000 +% 0000000000000000000000000000000000000000000000000000003388ddee995500000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000005599eedd883300000000000000000000000000 +% 000000000000000000001188ddffaa55000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 0000000000000000000000000000000000000000000000000000000000000000000066aaffdd8811 +% 0000000000000000000000000000000000000000000000000000000000000000001199ffbb440000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 000000000000000000000000000000000000000000000000000044bbff9911000000000000000000 +% 0000000000000000000000000000000000000000000000001188ddffaa5500000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 000000000000000066aaffdd881100000000000000000000 +% 00000000000000001188eecc66110000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 0000000000000000000000000000000000000000000000000000000000000000000000001166ccee +% 881100000000000000000000000000000000000000000000000000000000000033ddcc3300000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 0000000000000000000000000000000000000000000000000000000033ccdd330000000000000000 +% 000000000000000000000000000000000000000000001188eecc6611000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 000000000000000000001166ccee88110000000000000000 +% 0000000000000066eedd660000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000066 +% ddee660000000000000000000000000000000000000000000000000000000077ff88000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000088ff7700000000000000 +% 00000000000000000000000000000000000000000066eedd66000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 0000000000000000000000000066ddee6600000000000000 +% 000000000055dddd6600000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 0066dddd5500000000000000000000000000000000000000000000000000aaee4400000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 0000000000000000000000000000000000000000000000000000000000000044eeaa000000000000 +% 0000000000000000000000000000000000000055dddd660000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000066dddd550000000000 +% 0000000066ff77000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000077ff66000000000000000000000000000000000000000000000099cc110000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 000000000000000000000000000000000000000000000000000000000000000011cc990000000000 +% 00000000000000000000000000000000000066ff7700000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 000000000000000000000000000000000077ff6600000000 +% 00000088ee5500000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 0000000055ee8800000000000000000000000000000000000000000066ee33000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000033ee6600000000 +% 000000000000000000000000000000000088ee550000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000055ee88000000 +% 000099ee330000000000000000000000000000000000000000000000000000116600001166000000 +% 00000000001166000000000011660000000000000000000000000000000000000000000000000000 +% 00000000001111000000000000116600000000000000000000004400003300000000000000000000 +% 000000000033ee990000000000000000000000000000000000000033ee5500000000000000000000 +% 00000000000000000000000000000000000000000000000011110000000000001166000000000000 +% 0000000000000000000000000000000000000033000000000000000000000000000066ee33000000 +% 0000000000000000000000000000000099ee33000000000000000000000000000000000000000000 +% 00000000001166000011660000000000000000116600000000001166000000000000000000000000 +% 00000000000000000000000000000000000000111100000000000011660000000000000000000000 +% 0000003300000000000000000000000000000033ee990000 +% 0066ee3300000000000000000000bbffee11000088ffffff0000000000000033ff000033ff000000 +% 000000000055ff000000000033ff0000000000000000bbffffff8800000000000000000000000000 +% 0000000033660000000000000033ff0000000000000000001166ff00000077110000000000000000 +% 00000000000033ee66000000000000000000000000000000000000aa990000000000000000000000 +% bbffffff8800000000000000000000000000000000000033660000000000000055ff000000000000 +% 99dd00000000000000000000000000000000000077110000000000000000000000000099aa000000 +% 00000000000000000000000000000066ee3300000000000000000000bbffee11000088ffffff0000 +% 000000000033ff000033ff000000000000000055ff000000000033ff0000000000000000bbffffff +% 88000000000000000000000000000000000033660000000000000033ff00000000000000000066dd +% ffbb33007711000000000000000000000000000033ee6600 +% 00aa88000000000000000000000033ffddcc11000033ff330000000000000000ff000000ff000000 +% 000000000000ff000000000000ff00000000000000000033ff220000000000000000000000000000 +% 6600000088000000000000000000ff0000000000000000000000ff00000000880000000000000000 +% 0000000000000088aa000000000000000000000000000000000000ee440000000000000000000000 +% 0033ff220000000000000000000000000000660000000088000000000000000000ff000000000000 +% 000000000000000000000000000000006600000000880000000000000000000000000044ee000000 +% 000000000000000000000000000000aa88000000000000000000000033ffddcc11000033ff330000 +% 000000000000ff000000ff000000000000000000ff000000000000ff00000000000000000033ff22 +% 00000000000000000000000000006600000088000000000000000000ff0000000000000000447700 +% 1199dd00008800000000000000000000000000000088aa00 +% 11ff22000000000000000000000000ff33ee99000000ff000000000000000000ff000000ff000000 +% 000000000000ff000000000000ff00000000000000000000ff000000000000000000000000000000 +% dd00006655000000000000000000ff0000000000000000000000ff00000000774400000000000000 +% 0000000000000022ff110000000000000000000000000000000033ff000000000000000000000000 +% 0000ff000000000000000000000000000000dd0000006655000000000000000000ff000000000000 +% 00550000000000000000000000000000dd00000000774400000000000000000000000000ff330000 +% 000000000000000000000000000011ff22000000000000000000000000ff33ee99000000ff000000 +% 000000000000ff000000ff000000000000000000ff000000000000ff00000000000000000000ff00 +% 0000000000000000000000000000dd00006655000000000000000000ff0000000000000000220000 +% 0011ff00007744000000000000000000000000000022ff11 +% 77cc00000000000000000000000000ff0033ee880000ff00bbff0044ffff0000ff000000ff000088 +% eeff88000000ff99ffdd330000ff00000066ddffbb110000ff0044cc99ddff88000088ffff660088 +% ffff88bb2200001188eeffcc3300ff00000088ffff6600000000ff0000000033aa00000000000000 +% 0000000000000000cc770000000000000000000000000000000077aa000000000000000000000000 +% 0000ff000044cc99ddff88000088ffff6688ffff8800bb22000011bbffbb110000ff99ffdd330022 +% 88ff000066ddffbb111188eeffcc3388ffff88000033aa00000000000000000000000000bb770000 +% 000000000000000000000000000077cc00000000000000000000000000ff0033ee880000ff00bbff +% 0044ffff0000ff000000ff000088eeff88000000ff99ffdd330000ff00000066ddffbb110000ff00 +% 44cc99ddff88000088ffff660088ffff88bb2200001188eeffcc3300ff00000088ffff6600000000 +% 0011bb000033aa000000000000000000000000000000cc77 +% 77cc00000000000000000000000000ff000055ff6600ff0011ff000011ff0000ff000000ff0000aa +% 0033ff000000ff440099bb0000ff000044ffffffff880000ff0000ff660033ff0000ff2211440000 +% ff0000ff00000099991100884400ff000000ff22114400000000ff0000000000ee00000000000000 +% 0000000000000000cc770000000000000000000000000000000077aa000000000000000000000000 +% 0000ff000000ff660033ff0000ff22114400ff000000ff000000aa660099aa0000ff440099bb0000 +% 00ff0044ffffffff8899991100884400ff0000000000ee00000000000000000000000000bb770000 +% 000000000000000000000000000077cc00000000000000000000000000ff000055ff6600ff0011ff +% 000011ff0000ff000000ff0000aa0033ff000000ff440099bb0000ff000044ffffffff880000ff00 +% 00ff660033ff0000ff2211440000ff0000ff00000099991100884400ff000000ff22114400000000 +% 008833000000ee000000000000000000000000000000cc77 +% 11ff22000000000000000000000000ff00000066ee33ff0000ff000000ff0000ff000000ff000000 +% 1166ff000000ff000011ff0000ff00008877000000000000ff0000ff000000ff0000557711000000 +% ff0000ff000000ee110000000000ff0000005577110000000000ff0000000000ff00000000000000 +% 0000000000000022ff110000000000000000000000000000000033ff000000000000000000000000 +% 0000ff000000ff000000ff00005577110000ff000000ff000000ff000011ff0000ff000011ff0000 +% 00ff00887700000000ee110000000000ff0000000000ff00000000000000000000000000ff330000 +% 000000000000000000000000000011ff22000000000000000000000000ff00000066ee33ff0000ff +% 000000ff0000ff000000ff0000001166ff000000ff000011ff0000ff00008877000000000000ff00 +% 00ff000000ff0000557711000000ff0000ff000000ee110000000000ff0000005577110000000000 +% 335500000000ff000000000000000000000000000022ff11 +% 00aa88000000000000000000000000ff0000000088eeff0000ff000000ff0000ff000000ff000033 +% 3300ff000000ff000000ee0000ff0000aa99000000220000ff0000ff000000ff0000111177660000 +% ff0000ff000000ff220000001100ff0000001111776600000000ff0000000000ff00000000000000 +% 0000000000000088aa000000000000000000000000000000000000ee440000000000000000000000 +% 0000ff000000ff000000ff00001111776600ff000000ff000000ff220000ff0000ff000000ee0000 +% 00ff00aa9900000022ff220000001100ff0000000000ff00000000000000000000000044ee000000 +% 000000000000000000000000000000aa88000000000000000000000000ff0000000088eeff0000ff +% 000000ff0000ff000000ff0000333300ff000000ff000000ee0000ff0000aa99000000220000ff00 +% 00ff000000ff0000111177660000ff0000ff000000ff220000001100ff0000001111776600000033 +% 550000000000ff000000000000000000000000000088aa00 +% 0066ee330000000000000000000011ff440000000099ff0000ff330055ff0011ff220011ff2200ee +% 3344ff110000ff220088880011ff220066ff550044660022ff2211ff110011ff1100990033ff0000 +% ff1100bb220000aacc2200446611ff220000990033ff00000033ff1100000033aa00000000000000 +% 00000000000033ee66000000000000000000000000000000000000aa990000000000000000000000 +% 0022ff220011ff110011ff1100990033ff00ff110000bb220000aa990077990000ff220088880000 +% 00ff0066ff55004466aacc2200446600ff1100000033aa00000000000000000000000099aa000000 +% 00000000000000000000000000000066ee330000000000000000000011ff440000000099ff0000ff +% 330055ff0011ff220011ff2200ee3344ff110000ff220088880011ff220066ff550044660022ff22 +% 11ff110011ff1100990033ff0000ff1100bb220000aacc2200446611ff220000990033ff00003355 +% 000011550033aa0000000000000000000000000033ee6600 +% 000099ee33000000000000000000bbffff880000000099000088ffdd77cc44bbffff88bbffff88aa +% ee88dddd220099ffff880000bbffff880088ffee8800bbffffffe0ffff44ffffbb00ddffee770000 +% aaff776666000011aaffee8800bbffff8800ddffee77000044ffffff880000666600000000000000 +% 000000000033ee990000000000000000000000000000000000000033ee5500000000000000000000 +% bbffffff88bbffff44ffffbb00ddffee7700aaff77006666000011bbffbb11000099ffff88000000 +% 00ff000088ffee880011aaffee880000aaff7700006666000000000000000000000066ee33000000 +% 0000000000000000000000000000000099ee33000000000000000000bbffff880000000099000088 +% ffdd77cc44bbffff88bbffff88aaee88dddd220099ffff880000bbffff880088ffee8800bbffffff +% e0ffff44ffffbb00ddffee770000aaff776666000011aaffee8800bbffff8800ddffee770033eeff +% ffffff2200666600000000000000000000000033ee990000 +% 00000088ee5500000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000880000000000000000000000000000000000000000000000000000990000000000000000 +% 0000000055ee8800000000000000000000000000000000000000000066ee33000000000000000000 +% 00000000000000000000000000000000000000000000008800000000000000000000000000000000 +% 00ff0000000000000000000000000000000000000099000000000000000000000033ee6600000000 +% 000000000000000000000000000000000088ee550000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000088000000000000000000000000000000000000000000 +% 00000000009900000000000000000000000055ee88000000 +% 0000000066ff77000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000225500000000000000000000000000000000000000000000000077110000000000000000 +% 00000077ff66000000000000000000000000000000000000000000000099cc110000000000000000 +% 00000000000000000000000000000000000000000000002255000000000000000000000000003311 +% 00bb00000000000000000000000000000000000077110000000000000000000011cc990000000000 +% 00000000000000000000000000000000000066ff7700000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000022550000000000000000000000000000000000000000 +% 000000007711000000000000000000000077ff6600000000 +% 000000000055dddd6600000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000002211000000000000000000000000000000000000000000003300000000000000000000 +% 0066dddd5500000000000000000000000000000000000000000000000000aaee4400000000000000 +% 0000000000000000000000000000000000000000000000002211000000000000000000000000cccc +% 8833000000000000000000000000000000000033000000000000000000000044eeaa000000000000 +% 0000000000000000000000000000000000000055dddd660000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000221100000000000000000000000000000000000000 +% 00000033000000000000000000000066dddd550000000000 +% 0000000000000066eedd660000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000066 +% ddee660000000000000000000000000000000000000000000000000000000077ff88000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000088ff7700000000000000 +% 00000000000000000000000000000000000000000066eedd66000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 0000000000000000000000000066ddee6600000000000000 +% 00000000000000001188eecc66110000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 0000000000000000000000000000000000000000000000000000000000000000000000001166ddee +% 881100000000000000000000000000000000000000000000000000000000000033ddcc3300000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 0000000000000000000000000000000000000000000000000000000033ccdd330000000000000000 +% 000000000000000000000000000000000000000000001188eecc6611000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 000000000000000000001166ddee88110000000000000000 +% 000000000000000000001188ddffaa55000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 0000000000000000000000000000000000000000000000000000000000000000000066aaffdd8811 +% 0000000000000000000000000000000000000000000000000000000000000000001199ffbb440000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 000000000000000000000000000000000000000000000000000044bbff9911000000000000000000 +% 0000000000000000000000000000000000000000000000001188ddffaa5500000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 000000000000000066aaffdd881100000000000000000000 +% 000000000000000000000000003388ddee9955000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 000000000000000000000000000000000000000000000000000000000000005599eedd8833000000 +% 00000000000000000000000000000000000000000000000000000000000000000000002299ffbb44 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000044bbff99220000000000000000000000 +% 0000000000000000000000000000000000000000000000000000003388ddee995500000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000005599eedd883300000000000000000000000000 +% 000000000000000000000000000000003388ddeeaa77440000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 0000000000000000000000000000000000000000000000000000004477aaeedd8833000000000000 +% 000000000000000000000000000000000000000000000000000000000000000000000000002288ee +% cc772200000000000000000000000000000000000000000000000000000000000000000000000000 +% 0000000000000000000000000000000000000000002277ccee882200000000000000000000000000 +% 0000000000000000000000000000000000000000000000000000000000003388ddeeaa7744000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 004477aaeedd883300000000000000000000000000000000 +% 000000000000000000000000000000000000004488bbeeffbb885511000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000115588bbffeebb8844000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000011 +% 77ccffcc772200000000000000000000000000000000000000000000000000000000000000000000 +% 0000000000000000000000000000000000002277ccffcc7711000000000000000000000000000000 +% 0000000000000000000000000000000000000000000000000000000000000000004488bbeeffbb88 +% 55110000000000000000000000000000000000000000000000000000000000000000000000000000 +% 000000000000000000000000000000000000000000000000000000000000000000000000115588bb +% ffeebb884400000000000000000000000000000000000000 +% 0000000000000000000000000000000000000000000000337799ddffcc9988443300000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 000000000000000000000000000000000033448899ccffdd99773300000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00002277ccffcc885511000000000000000000000000000000000000000000000000000000000000 +% 0000000000000000000000000000115588ccffcc7722000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000337799 +% ddffcc99884433000000000000000000000000000000000000000000000000000000000000000000 +% 0000000000000000000000000000000000000000000000000000000000000033448899ccffdd9977 +% 330000000000000000000000000000000000000000000000 +% 000000000000000000000000000000000000000000000000000000226688bbccffffccbb88664411 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 0000000000000000000011446688d7ccffffccbb8866220000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000002277aaddffddb477440000000000000000000000000000000000000000000000000000 +% 000000000000000000004477b4ddffddaa7722000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00226688bbccffffccd7886644110000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000011446688bbccffffccbb886622000000 +% 000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000033448899bbeeff +% ffccbbbb888888444444000000000000000000000000000000000000000000000000000000000000 +% 444444888888bbbbccffffeebba7f8e6690000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000011b0f8cdffffddbb9988664422000000000000000000000000000000000000 +% 00002244668899bbddffffcdf8b01100000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 0000000000000069e6f0a7bbeeffffccbbbb88888844444400000000000000000000000000000000 +% 0000000000000000000000000000444444888888bbbbccffffeebb99884433000000000000000000 +% 000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000011 +% 444466888899bbbbeeffffffffffbbbbbbbbbbbbbbbbaa88888888aabbbbbbbbbbbbbbc4ffffffff +% ffeebbbb998888664444110000001188eebb33000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000001199ee33000033447788aabbeeffffffccbbbbbbbbbb99888899bbbbbbbbbbcc +% ffffffeebbaa88774433000033ee9911000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 000000000033bbee881100000011444466888899bbbbeeffffffffffc4bbbbbbbbbbbbbbaa888888 +% 88aabbbbbbbbbbbbbbbbffffffffffeebbbb99888866444411000000000000000000000000000000 +% 000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 000000000000000000000033444444444444778888888888888888888888887744448fe650443300 +% 000000000000000000000000000000001199ff992200000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 0000000000000011cccc220000000000000000000000334444444477888888888888888877444444 +% 4433000000000000000000000022cccc110000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 0000002299ff99110000000000000000000000000000000000334450f38f44447788888888888888 +% 88888888887744444444444433000000000000000000000000000000000000000000000000000000 +% 000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 0000000000000000000000000000000000000000000000000000000000000000000000dd88000000 +% 00000000000000000000000000000000000022bbee88110000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000033eeaa11000000000000000000000000000000000000000000000000000000000000 +% 000000000000000000000000000011aadd3300000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 001188eebb2200000000000000000000000000000000000000000088dd0000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 000000000000000000000000000000000000000000000000000000000000000000000044ee110000 +% 000000000000000000000000000000000000000044ccee6600000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 000000000055ee880000000000000000000000000000000000000000000000000000000000000000 +% 0000000000000000000000000000000088ee55000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 66eecc440000000000000000000000000000000000000000000011ee440000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 000000000000000000000000000000000000000000000000000000000000000000000000bb990000 +% 0000000000000000000000000000000000000000000066dddd440000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 0000000077ff66000000000000000000000000000000000000000000000000000000000000000000 +% 000000000000000000000000000000000066ff770000000000000000000000000000000000000000 +% 000000000000000000000000000000000000000000000000000000000000000000000000000044dd +% dd6600000000000000000000000000000000000000000000000099bb000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000033ff2200 +% 00000000000000000000000000000000000000000000001188eebb44000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000099ee4400000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000044ee9900000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000044bbee88 +% 1100000000000000000000000000000000000000000000000022ff33000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 0000000000000000000000000000000000000000000000000000000000000000000000000099bb00 +% 000000000000000000000000000000000000000000000000001199ff992200000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 0011cccc330000000000000000000000000000000000000000000000000000000000000000000000 +% 0000000000000000000000000000000000000033cccc110000000000000000000000000000000000 +% 000000000000000000000000000000000000000000000000000000000000000000002299ff991100 +% 00000000000000000000000000000000000000000000000000bb9900000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 0000000000000000000000000000000000000000000000000000000000000000000000000022ee44 +% 00000000000000000000000000000000000000000000000000000022aaff88110000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 33ccbb11000000000000000000000000000000000000000000000000000000000000000000000000 +% 000000000000000000000000000000000000000011bbcc3300000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000001188ffaa22000000 +% 00000000000000000000000000000000000000000000000044ee2200000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 000000000000000000000000000000000000000000000000000000000000000000000000000088cc +% 000000000000000000000000000000000000000000000000000000000044ccee6600000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000033 +% ee990000000000000000000000000000000000000000000000000000000000000000000000000000 +% 0000000000000000000000000000000000000000000099ee33000000000000000000000000000000 +% 0000000000000000000000000000000000000000000000000000000000000066eecc440000000000 +% 000000000000000000000000000000000000000000000000cc880000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 000000000000000000000000000000000000000000000000000000000000000000000000000011ee +% 6600000000000000000000000000000000000000000000000000000000000066dddd440000000000 +% 000000000000000000000000000000000000000000000000000000000000000000000000000066ff +% 77000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 000000000000000000000000000000000000000000000077ff660000000000000000000000000000 +% 000000000000000000000000000000000000000000000000000000000044dddd6600000000000000 +% 000000000000000000000000000000000000000000000066ee110000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000077 +% dd000000000000000000000000000000000000000000000000000000000000001188eebb22000000 +% 0000000000000000000000000000000000000000000000000000000000000000000000000088ee66 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000066ee8800000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000022bbee88110000000000000000 +% 0000000000000000000000000000000000000000000000dd77000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% dd8800000000000000000000000000000000000000000000000000000000000000002299ff881100 +% 00000000000000000000000000000000000000000000000000000000000000000000001199ee3300 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 0000000000000000000000000000000000000000000000000033ee99110000000000000000000000 +% 000000000000000000000000000000000000000000000000001188ff992200000000000000000000 +% 0000000000000000000000000000000000000000000088dd00000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 55ee1100000000000000000000000000000000000000000000000000000000000000000044bbee77 +% 0000000000000000000000000000000000000000000000000000000000000000000011cccc110000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 000000000000000000000000000000000000000000000000000022cccc1100000000000000000000 +% 00000000000000000000000000000000000000000000000088eebb44000000000000000000000000 +% 00000000000000000000000000000000000000000011ee5500000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00bb88000000000000000000000000000000000000000000000000000000000000000000000055dd +% dd550000000000000000000000000000000000000000000000000000000000000033ddaa11000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000011aadd33000000000000000000 +% 0000000000000000000000000000000000000000000055dddd550000000000000000000000000000 +% 00000000000000000000000000000000000000000088bb0000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 0044ff33000000000000000000000000000000000000000000000000000000000000000000000000 +% 88eebb330000000000000000000000000000000000000000000000000000000055ee990000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 000000000000000000000000000000000000000000000000000000000099ee550000000000000000 +% 000000000000000000000000000000000000000033bbee8800000000000000000000000000000000 +% 000000000000000000000000000000000000000033ff440000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 000088cc000000000000000000000000000000000000000000000000000000000000000000000000 +% 001199ff99110000000000000000000000000000000000000000000000000066ff66000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000066ff6600000000000000 +% 0000000000000000000000000000000000001199ff99110000000000000000000000000000000000 +% 0000000000000000000000000000000000000000cc88000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 000011dd770000000000000000000000000000000000000000000000000000000000000000000000 +% 00000022bbee88110000000000000000000000000000000000000000000099ee5500000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 0000000000000000000000000000000000000000000000000000000000000055ee99000000000000 +% 000000000000000000000000000000001188eebb2200000000000000000000000000000000000000 +% 0000000000000000000000000000000000000077dd11000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000055ee2200000000000000000000000000000000000000000000000000000000000000000000 +% 000000000044dddd550000000000000000000000000000000000000011aadd330000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 000000000000000000000000000000000000000000000000000000000000000033ddaa1100000000 +% 00000000000000000000000000000055dddd44000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000022ee5500000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000aaaa00000000000000000000000000000000000000000000000000000000000000000000 +% 0000000000000077eebb330000000000000000000000000000000022cccc11000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000011cccc11000000 +% 0000000000000000000000000033bbee770000000000000000000000000000000000000000000000 +% 000000000000000000000000000000000000aaaa0000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 0000000022ee55000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000001199ff88110000000000000000000000000033ee991100000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 000000000000000000000000000000000000000000000000000000000000000000001199ee330000 +% 00000000000000000000001188ff9911000000000000000000000000000000000000000000000000 +% 000000000000000000000000000000000055ee220000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 000000000077ee110000000000000000000000000000000000000000000000000000000000000000 +% 0000000000000000000033bbee77000000000000000000000066ee88000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000088ee6600 +% 0000000000000000000077eebb330000000000000000000000000000000000000000000000000000 +% 0000000000000000000000000000000011ee77000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 000000000000bb880000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000066eecc44000000000000000077ff6600000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 0000000000000000000000000000000000000000000000000000000000000000000000000066ff77 +% 000000000000000044ccee6600000000000000000000000000000000000000000000000000000000 +% 0000000000000000000000000000000088bb00000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000033ff4400000000000000000000000000000000000000000000000000000000000000 +% 000000000000000000000000001188ff9922000000000099ee330000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 000000000000000000000000000000000000000000000000000000000000000000000000000033ee +% 9900000000002299ff88110000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000044ff3300000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 0000000000000088cc00000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000022bbee88000011bbcc33000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000033 +% ccbb11000088eebb2200000000000000000000000000000000000000000000000000000000000000 +% 000000000000000000000000000000cc880000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 0000000000000011dd88000000000000000000000000000000000000000000000000000000000000 +% 000000000000000000000000000000000044dddd69cccc1100000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 11cccc69dddd44000000000000000000000000000000000000000000000000000000000000000000 +% 000000000000000000000000000088dd110000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 000000000000000044ff220000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000a8fee4220000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 0022e4fea80000000000000000000000000000000000000000000000000000000000000000000000 +% 0000000000000000000000000022ff44000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 000000000000000000aabb0000662200000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000066ff8999ff8811000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000011 +% 88ff9989ff6600000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000022660000bb9900000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000011ee99ebffbb00000000000000000000000000000000000000000000000000 +% 000000000000000000000000000000000088ee55000044ccdd550000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 000000000000000000000000000000000000000000000000000000000000000000000000000055ee +% cc44000055ee88000000000000000000000000000000000000000000000000000000000000000000 +% 000000000000000000bbffeb99ee1100000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000066eefbffffeb00000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000011aadd33000000000077eebb22000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000022bbee77 +% 000000000033eeaa1100000000000000000000000000000000000000000000000000000000000000 +% 000000000000000000ebfffffbee6600000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 0000000000000022ebfbffffffffff11000000000000000000000000000000000000000000000000 +% 000000000000000000223300000022cccc110000000000000011aaee880000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 000000000000000000000000000000000000000000000000000000000000000000000088eeaa1100 +% 00000000000011cccc22000000332200000000000000000000000000000000000000000000000000 +% 000000000000000011fffffffffffbeb220000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 0000000000000044fffffffffffff644000000000000000000000000000000000000000000000000 +% 000000000000000011f5ff660033ee99110000000000000000000044ddcc44000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000044ccdd44000000 +% 000000000000001199ee330066ffeb11000000000000000000000000000000000000000000000000 +% 000000000000000044f6ffffffffffff440000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 000000000000000033f5ffffffffff88000000000000000000000000000000000000000000000000 +% 000000000000000090fbffff8fee88000000000000000000000000001188ff991100000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 000000000000000000000000000000000000000000000000000000000000001199ff881100000000 +% 00000000000000000088ee8ffffffb90000000000000000000000000000000000000000000000000 +% 000000000000000088fffffffffff533000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000033ebfaffffffbb000000000000000000000000000000000000000000000000 +% 0000000000000022f8ffffffff8f0000000000000000000000000000000033bbee66000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000066eebb33000000000000 +% 000000000000000000008ffffffffff8220000000000000000000000000000000000000000000000 +% 0000000000000000bbfffffffaeb3300000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 0000000000000000000011d7fcffffeb000000000000000000000000000000000000000000000000 +% 00000000000000a0fbffffffffff66000000000000000000000000000000000077eebb2200000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 0000000000000000000000000000000000000000000000000000000022bbee660000000000000000 +% 00000000000000000066fffffffffffba00000000000000000000000000000000000000000000000 +% 0000000000000000ebfffffcd7110000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 000000000000000000000011bbf9ffff110000000000000000000000000000000000000000000000 +% 00000000000033ffffffffffffffff5500000000000000000000000000000000001199ff88000000 +% 00002244000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000003322000000000088ff9911000000000000000000 +% 000000000000000055ffffffffffffffff3300000000000000000000000000000000000000000000 +% 0000000000000011fffff9bb11000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000a0fcff440000000000000000000000000000000000000000000000 +% 000000000000c4ffffffffffffffe9220000000000000000000000000000000000000044dddd4400 +% 0000ebff330000000000000000000000000000000000000000000000000000000000000000000000 +% 0000000000000000000000000000000000000033ffeb00000044dddd440000000000000000000000 +% 000000000000000022e9ffffffffffffffc400000000000000000000000000000000000000000000 +% 0000000000000044fffca00000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 000000000000000000000000000080ff882244444444888888888888888844444444220000000000 +% 000000000044fbfffffffbffa744000000000000000000000000000000000000000000000088ff99 +% 1166fbfff53300000000000000000000000000000000000000114444448888888888884444441100 +% 00000000000000000000000000000000000033f5fffb661199ff8800000000000000000000000000 +% 0000000000000000000044a7fffbfffffffb44000000000000000000002244444444888888888888 +% 8888444444442288ff80000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 0000000000000000000022447788bbdaffffffccbbbbbbbbaa8888aabbbbbbbbccffffffccbb8877 +% 4422000000e6ffffffe97711000000000000000000000000000000000000000000000000000022bb +% eeeeffffffeb1100000000000000000000000000225588bbddffffbbbbbbbb8888bbbbbbbbffffdd +% bb8855220000000000000000000000000011ebffffffeeeebb220000000000000000000000000000 +% 0000000000000000000000001177e9ffffffe600000022447788bbccffffffccbbbbbbbbaa8888aa +% bbbbbbbbccffffffdabb887744220000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 000000000000226699ddffddbb8888443300000000000000000000000000000000000033448888bb +% eeffdd99a3ffffa74400000000000000000000000000000000000000000000000000000000000000 +% 99fbfffffffad7110000000000000000002277ccffccaa8844110000000000000000000000001144 +% 88aaccffcc772200000000000000000011d7fafffffffb9900000000000000000000000000000000 +% 00000000000000000000000000000044a7ffffa399ddffddbb888844330000000000000000000000 +% 0000000000000033448888bbeeffdd99662200000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 0000005599ddffcc8855110000000000000000000000000000000000000000000000000000000000 +% 00115588d0ffe0995500000000000000000000000000000000000000000000000000000000000000 +% ebfffffffffffcbb0000000000000066ccffcc772200000000000000000000000000000000000000 +% 0000002277ccffcc6600000000000000bbfcffffffffffeb00000000000000000000000000000000 +% 0000000000000000000000000000005599e0ffd08855110000000000000000000000000000000000 +% 00000000000000000000000000115588ccffdd995500000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 2288ddee995511000000000000000000000000000000000000000000000000000000000000000000 +% 0000000000115599eedd882200000000000000000000000000000000000000000000000000000066 +% fffffffffffffff9a00000000066dddd772200000000000000000000000000000000000000000000 +% 0000000000002277dddd6600000000a0f9ffffffffffffff66000000000000000000000000000000 +% 0000000000000000000000002288ddee995511000000000000000000000000000000000000000000 +% 0000000000000000000000000000000000115599eedd882200000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 000000000000000000000000000000000000000000000000000000000000000000000000000066bb +% ffaa6600000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000066aaffbb660000000000000000000000000000000000000000000000000022 +% bbebfff6fffffffffc800066dddd6600000000000000000000000000000000000000000000000000 +% 00000000000000000066dddd660080fcfffffffff6ffebbb22000000000000000000000000000000 +% 0000000000000000000066bbffaa6600000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000066aaffbb660000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000055dddd88 +% 22000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000002288dddd55000000000000000000000000000000000000000000000000 +% 0000114488bbebffffffc1ee66000000000000000000000000000000000000000000000000000000 +% 000000000000000000000066eec1ffffffebbb884411000000000000000000000000000000000000 +% 000000000000000055dddd8822000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000002288dddd55000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 0000000000000000000000000000000000000000000000000000000000000000000044bbee880000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 000000000000000000000000000088eebb4400000000000000000000000000000000000000000000 +% 000000000000001169f0c01100000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000011c0f069110000000000000000000000000000000000000000000000 +% 00000000000044bbee88000000000000000000000000000000000000000000000000000000000000 +% 000000000000000000000000000000000000000000000000000088eebb4400000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000001199ff8811000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 0000000000000000000000000000001188ff99110000000000000000000000000000000000000000 +% 0000000000000066ff88000000000000000000000000000000000000000000000000000000000000 +% 000000000000000000000000000088ff660000000000000000000000000000000000000000000000 +% 000000001199ff881100000000000000000000000000000000000000000000000000000000000000 +% 0000000000000000000000000000000000000000000000000000001188ff99110000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 0000000000000000000000000000000000000000000000000000000000000011cccc220000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 000000000000000000000000000000000022cccc1100000000000000000000000000000000000000 +% 00000000000066ff5500000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000055ff6600000000000000000000000000000000000000000000 +% 00000011cccc22000000000000000000000000000000000000000000000000000000000000000000 +% 000000000000000000000000000000000000000000000000000000000022cccc1100000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000033eeaa11000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000011aaee33000000000000000000000000000000000000 +% 000000000033ee660000000000000000000000000000000000000000000000000000000000000000 +% 0000000000000000000000000000000066ee33000000000000000000000000000000000000000000 +% 000033eeaa1100000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000011aaee33000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 000000000000000000000000000000000000000000000000000000000044ee880000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 000000000000000000000000000000000000000088ee440000000000000000000000000000000000 +% 0000000022ee88000000000000000000000000000000000000000000000000000000000000000000 +% 000000000000000000000000000000000088ee220000000000000000000000000000000000000000 +% 0044ee88000000000000000000000000000000000000000000000000000000000000000000000000 +% 000000000000000000000000000000000000000000000000000000000000000088ee440000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 0000000000000000000000000000000000000000000000000000000011ee77000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000077ee1100000000000000000000000000000000 +% 0000000099aa00000000000000000000000000000000000000000000000000000000000000000000 +% 000000000000000000000000000000000000aa990000000000000000000000000000000000000000 +% 11ee7700000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000077ee1100000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000aabb00000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000bbaa00000000000000000000000000000000 +% 00000022ff2200000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000022ff2200000000000000000000000000000000000000 +% aabb0000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000bbaa00000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000055ee2200000000000000000000 +% 00000000000000000000000000000000000000000000001111000000000011660000000000000000 +% 0000004400000033000000000000000000000000000022ee55000000000000000000000000000000 +% 00000099990000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000999900000000000000000000000000000000000055 +% ee220000000000000000000000000000000000000000000000000000000000000000001111000000 +% 0000116600000000000000000000000000000033000000000000000000000000000022ee55000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 000000000000000000000000000000000000000000000000000000cc7700000000000000000000bb +% ffffff88000000000000000000000000000000000000336600000000000033ff0000000000000000 +% 001166ff0000000077110000000000000000000000000077cc000000000000000000000000000000 +% 000000ff330000000000000000000000bbffee11000088ffffff0000000000000000000000000000 +% 0000000000000000000000000000000000000033ff000000000000000000000000000000000000cc +% 7700000000000000000000bbffffff88000000000000000000000000000000000000336600000000 +% 000033ff00000000000000000066ddffbb33000077110000000000000000000000000077cc000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 000000000000000000000000000000000000000000000000000000ff220000000000000000000000 +% 33ff2200000000000000000000000000006600000000880000000000000000ff0000000000000000 +% 000000ff0000000000880000000000000000000000000022ff000000000000000000000000000000 +% 000033ff00000000000000000000000033ffddcc11000033ff330000000000000000000000000000 +% 0000000000000000000000000000000000000000ff330000000000000000000000000000000000ff +% 22000000000000000000000033ff2200000000000000000000000000006600000000880000000000 +% 000000ff00000000000000004477001199dd000000880000000000000000000000000022ff000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 000000000000000000000000000000000000000000000000000044ee000000000000000000000000 +% 00ff000000000000000000000000000000dd00000066550000000000000000ff0000000000000000 +% 000000ff0000000000774400000000000000000000000000ee440000000000000000000000000000 +% 000055cc00000000000000000000000000ff33ee99000000ff000000000000000000000000000000 +% 0000000000000000000000000000000000000000cc550000000000000000000000000000000044ee +% 00000000000000000000000000ff000000000000000000000000000000dd00000066550000000000 +% 000000ff00000000000000002200000011ff000000774400000000000000000000000000ee440000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 000000000000000000000000000000000000000000000000000088aa000000000000000000000000 +% 00ff000044cc99ddff88000088ffff6688ffff8800bb22001188eeffcc3300ff00000088ffff6600 +% 000000ff000000000033aa00000000000000000000000000aa880000000000000000000000000000 +% 000088aa00000000000000000000000000ff0033ee880000ff000011bbffbb110044cc99ddff8800 +% 0066ddffbb110000000000000000000000000000aa880000000000000000000000000000000088aa +% 00000000000000000000000000ff000044cc99ddff88000088ffff6688ffff8800bb22001188eeff +% cc3300ff00000088ffff66000000000011bb00000033aa00000000000000000000000000aa880000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 000000000000000000000000000000000000000000000000000088aa000000000000000000000000 +% 00ff000000ff660033ff0000ff22114400ff000000ff000099991100884400ff000000ff22114400 +% 000000ff000000000000ee00000000000000000000000000aa880000000000000000000000000000 +% 000088aa00000000000000000000000000ff000055ff6600ff0000aa660099aa0000ff660033ff00 +% 44ffffffff880000000000000000000000000000aa880000000000000000000000000000000088aa +% 00000000000000000000000000ff000000ff660033ff0000ff22114400ff000000ff000099991100 +% 884400ff000000ff2211440000000000883300000000ee00000000000000000000000000aa880000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 000000000000000000000000000000000000000000000000000044ee000000000000000000000000 +% 00ff000000ff000000ff00005577110000ff000000ff0000ee110000000000ff0000005577110000 +% 000000ff000000000000ff00000000000000000000000000ee440000000000000000000000000000 +% 000055cc00000000000000000000000000ff00000066ee33ff0000ff000011ff0000ff000000ff00 +% 8877000000000000000000000000000000000000cc550000000000000000000000000000000044ee +% 00000000000000000000000000ff000000ff000000ff00005577110000ff000000ff0000ee110000 +% 000000ff000000557711000000000033550000000000ff00000000000000000000000000ee440000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 000000000000000000000000000000000000000000000000000000ff220000000000000000000000 +% 00ff000000ff000000ff00001111776600ff000000ff0000ff220000001100ff0000001111776600 +% 000000ff000000000000ff00000000000000000000000022ff000000000000000000000000000000 +% 000033ff00000000000000000000000000ff0000000088eeff0000ff220000ff0000ff000000ff00 +% aa99000000220000000000000000000000000000ff330000000000000000000000000000000000ff +% 22000000000000000000000000ff000000ff000000ff00001111776600ff000000ff0000ff220000 +% 001100ff000000111177660000003355000000000000ff00000000000000000000000022ff000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 000000000000000000000000000000000000000000000000000000cc770000000000000000000000 +% 22ff220011ff110011ff1100990033ff00ff110000bb2200aacc2200446611ff220000990033ff00 +% 000033ff110000000033aa00000000000000000000000077cc000000000000000000000000000000 +% 000000ff33000000000000000000000011ff440000000099ff0000aa990077990011ff110011ff11 +% 66ff550044660000000000000000000000000033ff000000000000000000000000000000000000cc +% 77000000000000000000000022ff220011ff110011ff1100990033ff00ff110000bb2200aacc2200 +% 446611ff220000990033ff0000335500001155000033aa00000000000000000000000077cc000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000055ee22000000000000000000bb +% ffffff88bbffff44ffffbb00ddffee7700aaff770066660011aaffee8800bbffff8800ddffee7700 +% 0044ffffff880000006666000000000000000000000022ee55000000000000000000000000000000 +% 00000099990000000000000000000000bbffff880000000099000011bbffbb1100bbffff44ffffbb +% 0088ffee880000000000000000000000000000999900000000000000000000000000000000000055 +% ee22000000000000000000bbffffff88bbffff44ffffbb00ddffee7700aaff770066660011aaffee +% 8800bbffff8800ddffee770033eeffffffff2200006666000000000000000000000022ee55000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000aabb00000000000000000000 +% 00000000000000000000000000000000000000000000880000000000000000000000000000000000 +% 00000000000000000099000000000000000000000000bbaa00000000000000000000000000000000 +% 00000022ff2200000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000022ff2200000000000000000000000000000000000000 +% aabb0000000000000000000000000000000000000000000000000000000000000000880000000000 +% 00000000000000000000000000000000000000000099000000000000000000000000bbaa00000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 0000000000000000000000000000000000000000000000000000000011ee77000000000000000000 +% 00000000000000000000000000000000000000000000225500000000000000000000000000000000 +% 00000000000000007711000000000000000000000077ee1100000000000000000000000000000000 +% 0000000099aa00000000000000000000000000000000000000000000000000000000000000000000 +% 000000000000000000000000000000000000aa990000000000000000000000000000000000000000 +% 11ee7700000000000000000000000000000000000000000000000000000000000000225500000000 +% 00000000000000000000000000000000000000007711000000000000000000000077ee1100000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 000000000000000000000000000000000000000000000000000000000044ee880000000000000000 +% 00000000000000000000000000000000000000000000002211000000000000000000000000000000 +% 000000000000003300000000000000000000000088ee440000000000000000000000000000000000 +% 0000000022ee88000000000000000000000000000000000000000000000000000000000000000000 +% 000000000000000000000000000000000088ee220000000000000000000000000000000000000000 +% 0044ee88000000000000000000000000000000000000000000000000000000000000002211000000 +% 000000000000000000000000000000000000003300000000000000000000000088ee440000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000033eeaa11000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000011aaee33000000000000000000000000000000000000 +% 000000000033ee660000000000000000000000000000000000000000000000000000000000000000 +% 0000000000000000000000000000000066ee33000000000000000000000000000000000000000000 +% 000033eeaa1100000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000011aaee33000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 0000000000000000000000000000000000000000000000000000000000000011cccc220000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 000000000000000000000000000000000022cccc1100000000000000000000000000000000000000 +% 00000000000066ff5500000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000055ff6600000000000000000000000000000000000000000000 +% 00000011cccc22000000000000000000000000000000000000000000000000000000000000000000 +% 000000000000000000000000000000000000000000000000000000000022cccc1100000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000001199ff8811000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 0000000000000000000000000000001188ff99110000000000000000000000000000000000000000 +% 0000000000000066ff88000000000000000000000000000000000000000000000000000000000000 +% 000000000000000000000000000088ff660000000000000000000000000000000000000000000000 +% 000000001199ff881100000000000000000000000000000000000000000000000000000000000000 +% 0000000000000000000000000000000000000000000000000000001188ff99110000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 0000000000000000000000000000000000000000000000000000000000000000000044bbee880000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 000000000000000000000000000088eebb4400000000000000000000000000000000000000000000 +% 000000000000000033ddbb1100000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000011bbdd33000000000000000000000000000000000000000000000000 +% 00000000000044bbee88000000000000000000000000000000000000000000000000000000000000 +% 000000000000000000000000000000000000000000000000000088eebb4400000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000055dddd88 +% 22000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000002288dddd55000000000000000000000000000000000000000000000000 +% 00000000000000000011aaee66000000000000000000000000000000000000000000000000000000 +% 000000000000000000000066eeaa1100000000000000000000000000000000000000000000000000 +% 000000000000000055dddd8822000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000002288dddd55000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 000000000000000000000000000000000000000000000000000000000000000000000000000066bb +% ffaa6600000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000066aaffbb660000000000000000000000000000000000000000000000000000 +% 000000000000000000000066dddd6600000000000000000000000000000000000000000000000000 +% 00000000000000000066dddd66000000000000000000000000000000000000000000000000000000 +% 0000000000000000000066bbffaa6600000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000066aaffbb660000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 2288ddee995511000000000000000000000000000000000000000000000000000000000000000000 +% 0000000000115599eedd882200000000000000000000000000000000000000000000000000000000 +% 0000000000000000000000000066dddd772200000000000000000000000000000000000000000000 +% 0000000000002277dddd660000000000000000000000000000000000000000000000000000000000 +% 0000000000000000000000002288ddee995511000000000000000000000000000000000000000000 +% 0000000000000000000000000000000000115599eedd882200000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 0000005599ddffcc8855110000000000000000000000000000000000000000000000000000000000 +% 00115588ccffdd995500000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000066ccffcc772200000000000000000000000000000000000000 +% 0000002277ccffcc6600000000000000000000000000000000000000000000000000000000000000 +% 0000000000000000000000000000005599ddffcc8855110000000000000000000000000000000000 +% 00000000000000000000000000115588ccffdd995500000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 000000000000226699ddffeebb8888443300000000000000000000000000000000000033448888bb +% eeffdd998ff188000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000002277ccffccaa8844110000000000000000000000001144 +% 88aaccffcc7722000000000000000000000000000000000000000000000000000000000000000000 +% 000000000000000000000000000000000088f18f99ddffeebb888844330000000000000000000000 +% 0000000000000033448888bbeeffdd99662200000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 0000000000000000000022447788bbccffffffccbbbbbbbbaa8888aabbbbbbbbccffffffccbb8877 +% 442200000033ee991100000000000000000000000000000000000000000000000000000000000000 +% 0000000000000000000000000000000000000000225588bbddffffbbbbbbbb8888bbbbbbbbffffdd +% bb885522000000000000000000000000000000000000000000000000000000000000000000000000 +% 0000000000000000000000000000001199ee3300000022447788bbccffffffccbbbbbbbbaa8888aa +% bbbbbbbbccffffffccbb887744220000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000002244444444888888888888888844444444220000000000 +% 00000000000022cccc11000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000114444448888c8c888884444441100 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 000000000000000000000000000011cccc2200000000000000000000002244444444888888888888 +% 88884444444422000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 0000000000000011aaee330000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000888800000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 0000000000000000000000000033eeaa110000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000088ee5500000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000888800000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000055ee8800000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 0000000000000000000066ff77000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000888800000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 000000000000000000000077ff660000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 000000000000000000000044ee990000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000888800000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 0000000000000000000099ee33000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000033cccc11000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000888800000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 000000000000000011cccc3300000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 0000000000000000000000000011bbcc330000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000888800000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 0000000000000033ddbb110000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000099ee4400000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000888800000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000044ee9900000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 0000000000000000000000000000000066ff66000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000888800000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 000000000066ff660000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 000000000000000000000000000000000055ee990000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000888800000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 0000000099ee55000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000033ddaa11000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000888800000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 000011aadd3300000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 0000000000000000000000000000000000000011cccc220000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000888800000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 0022cccc110000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000001199ee3300000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000888800000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 33ee9911000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 0000000000000000000000000000000000000000000088ff66000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000888800000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000066 +% ff880000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 000000000000000000000000000000000000000000000066ee880000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000888800000000000000 +% 000000000000000000000000000000000000000000000000000000000000000000000000000088ee +% 66000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000033ee9911000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000888800000000000000 +% 0000000000000000000000000000000000000000000000000000000000000000000000001199ee33 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 0000000000000000000000000000000000000000000000000011cccc220000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000888800000000000000 +% 000000000000000000000000000000000000000000000000000000000000000000000022cccc1100 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000001199ee3300000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000888800000000000000 +% 0000000000000000000000000000000000000000000000000000000000000000000033ee99110000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 0000000000000000000000000000000000000000000000000000000088ff66000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000888800000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000066ff8800000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 000000000000000000000000000000000000000000000000000000000066ee880000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000888800000000000000 +% 000000000000000000000000000000000000000000000000000000000000000088ee660000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000033eeaa11000000000000 +% 00000000000000000000000000000000000000000000000000000000000000888800000000000000 +% 00000000000000000000000000000000000000000000000000000000000011aaee33000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 0000000000000000000000000000000000000000000000000000000000000011cccc220000000000 +% 00000000000000000000000000000000000000000000000000000000000000888800000000000000 +% 000000000000000000000000000000000000000000000000000000000022cccc1100000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000001199ee3300000000 +% 00000000000000000000000000000000000000000000000000000000000000888800000000000000 +% 0000000000000000000000000000000000000000000000000000000033ee99110000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 0000000000000000000000000000000000000000000000000000000000000000000088ff66000000 +% 00000000000000000000000000000000000000000000000000000000000000888800000000000000 +% 00000000000000000000000000000000000000000000000000000066ff8800000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 000000000000000000000000000000000000000000000000000000000000000000000055ee990000 +% 00000000000000000000000000000000000000000000000000000000000000888800000000000000 +% 000000000000000000000000000000000000000000000000000099ee550000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000033cccc11 +% 00000000000000000000000000000000000000000000000000000000338888c8c888888822000000 +% 00000000000000000000000000000000000000000000000011cccc33000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 0000000000000000000000000000000000000000000000000000000000000000000000000011aaee +% 3300000000000000000000000000000000000000000000000000000077fdffffffffffff66000000 +% 000000000000000000000000000000000000000000000033eeaa1100000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000088 +% ee66000000000000000000000000000000000000000000000000000022fffffffffffff811000000 +% 0000000000000000000000000000000000000000000066ff88000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 66ee880000000000000000000000000000000000000000000000000000e9ffffffffffa700000000 +% 00000000000000000000000000000000000000000088ee6600000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 0033ddbb1100000033220000000000000000000000000000000000000090ffffffffff3300000000 +% 0000000000000000000000000000223300000011bbdd330000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 000011bbdd330066ffeb1100000000000000000000000000000000000044faffffffdd0000000000 +% 0000000000000000000000000011f5ff660033ddbb11000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 0000000088ee85fffffb9000000000000000000000000000000000000000f6fffffb660000000000 +% 0000000000000000000000000090fbffff8fee880000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000008ffffffffff822000000000000000000000000000000000000a7fffff8110000000000 +% 00000000000000000000000022f8ffffffff8f000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 0000000066fffffffffffba000000000000000000000000000000000000066f9ffa7000000000000 +% 000000000000000000000000a0fbffffffffff660000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000055ffffffffffffffff33000000000000000000000000000000000011ffff33000000000000 +% 000000000000000000000033ffffffffffffffff5500000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000022e9ffffffffffffffc4000000000000000000000022444444668888e6f088886644444422 +% 0000000000000000000000c4ffffffffffffffe92200000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 000000000044a7fffbfffffffb440000000022448899bbffffffccbbbbbbbb9898bbbbbbbbccffff +% ffbb998844220000000044fbfffffffbffa744000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 000000000000001177e9ffffffe6004488ccffddbb88664400000000000000000000000000000000 +% 446688bbddffcc884400e6ffffffe977110000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 0000000000000000000044a7fffff5eeaa6622000000000000000000000000000000000000000000 +% 00000000002266aaeef5ffffa7440000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 0000000000000000001188dde0c05000000000000000000000000000000000000000000000000000 +% 00000000000000000050c0e0dd881100000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 000000000000002299eecc6600000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000066ccee99220000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000088ff9944000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000004499ff8800000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 0000000033ccdd440000000000000000000000000000000000000000000000000000000000000000 +% 0000000000000000000000000000000044ddcc330000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000088ff8811000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000001188ff8800000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 000099ee330000000000000000000000000000000000000000000000000000000000000000000000 +% 0000000000000000000000000000000000000033ee99000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 0099ee33000000000000000000000000000000000000000000000000000000000000000000000000 +% 000000000000000000000000000000000000000033ee990000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 99ee3300000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000033ee9900000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000055 +% ee330000000000000000000000000000000000000000000000000000000000000000000000000000 +% 0000000000000000000000000000000000000000000033ee44000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 000000000000000000000000000000000000000000000000000000000000000000000000000000dd +% 88000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 000000000000000000000000000000000000000000000088dd000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 000000000000000000000000000000000000000000000000000000000000000000000000000088dd +% 00000000000000000000000000220000000000000000000000000000000000000000000000000000 +% 000000000000000000000000000000000000000000000000dd880000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 0000000000000000000000000000000000000000000000000000000000000000000000000000ee55 +% 00000000000000000000bbffff224444882200000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000055ee0000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 0000000000000000000000000000000000000000000000000000000000000000000000000022ff11 +% 000000000000000000000033ff00000011dd00000000000000000066000000660000000000000000 +% 00000000000000000000000000000000000000000000000011ff2200000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 0000000000000000000000000000000000000000000000000000000000000000000000000044dd00 +% 000000000000000000000000ff00000011ff000000000000000000dd000000dd0000000000000000 +% 00000000000000000000000000000000000000000000000000dd4400000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 0000000000000000000000000000000000000000000000000000000000000000000000000088aa00 +% 000000000000000000000000ff0000229988000011bbffbb110088ffff8888ffff880011bbffbb11 +% 0044cc88ccffbb88eeff880000000000000000000000000000aa8800000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 0000000000000000000000000000000000000000000000000000000000000000000000000088aa00 +% 000000000000000000000000ffffffffaa110000aa660099aa0000ff000000ff000000aa660099aa +% 0000ff550033ff440033ff0000000000000000000000000000aa8800000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 0000000000000000000000000000000000000000000000000000000000000000000000000044dd00 +% 000000000000000000000000ff00003399bb0000ff000011ff0000ff000000ff000000ff000011ff +% 0000ff000000ff000000ff0000000000000000000000000000dd4400000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 0000000000000000000000000000000000000000000000000000000000000000000000000022ff11 +% 000000000000000000000000ff00000000ff0000ff220000ff0000ff000000ff000000ff220000ff +% 0000ff000000ff000000ff0000000000000000000000000011ff2200000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 0000000000000000000000000000000000000000000000000000000000000000000000000000ee55 +% 000000000000000000000033ff11002288bb0000aa990077990000ff110000ff110000aa99007799 +% 0011ff110011ff110011ff1100000000000000000000000055ee0000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 000000000000000000000000000000000000000000000000000000000000000000000000000088dd +% 00000000000000000000bbffffffffffaa11000011bbffbb110000aaff7700aaff770011bbffbb11 +% 00bbffff44ffffff88ffffbb000000000000000000000000dd880000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 000000000000000000000000000000000000000000000000000000000000000000000000000000dd +% 88000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 000000000000000000000000000000000000000000000088dd000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000055 +% ee330000000000000000000000000000000000000000000000000000000000000000000000000000 +% 0000000000000000000000000000000000000000000033ee44000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 99ee3300000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000033ee9900000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 0099ee33000000000000000000000000000000000000000000000000000000000000000000000000 +% 000000000000000000000000000000000000000033ee990000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 000099ee330000000000000000000000000000000000000000000000000000000000000000000000 +% 0000000000000000000000000000000000000033ee99000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000088ff8811000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000001188ff8800000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 0000000033ccdd440000000000000000000000000000000000000000000000000000000000000000 +% 0000000000000000000000000000000044ddcc330000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000088ff9944000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000004499ff8800000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 000000000000002299eecc6600000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000066ccee99220000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 0000000000000000001188dddd884400000000000000000000000000000000000000000000000000 +% 0000000000000000004488dddd881100000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000066aaeeeeaa6622000000000000000000000000000000000000000000 +% 00000000002266aaeeeeaa6600000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 0000000000000000000000000000004488ccffddbb88664400000000000000000000000000000000 +% 446688bbddffcc884400000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000022448899bbffffffccbbbbbbbb8888bbbbbbbbccffff +% ffbb9988442200000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000022444444668888888888886644444422 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 000000000000000000000000000000000000000000000000 +%%EndImage +%%EndPreview +save countdictstack mark newpath /showpage {} def /setpagedevice {pop} def +%%EndProlog +%%Page 1 1 +save +/DotDict 200 dict def +DotDict begin + +/setupLatin1 { +mark +/EncodingVector 256 array def + EncodingVector 0 + +ISOLatin1Encoding 0 255 getinterval putinterval + +EncodingVector + dup 306 /AE + dup 301 /Aacute + dup 302 /Acircumflex + dup 304 /Adieresis + dup 300 /Agrave + dup 305 /Aring + dup 303 /Atilde + dup 307 /Ccedilla + dup 311 /Eacute + dup 312 /Ecircumflex + dup 313 /Edieresis + dup 310 /Egrave + dup 315 /Iacute + dup 316 /Icircumflex + dup 317 /Idieresis + dup 314 /Igrave + dup 334 /Udieresis + dup 335 /Yacute + dup 376 /thorn + dup 337 /germandbls + dup 341 /aacute + dup 342 /acircumflex + dup 344 /adieresis + dup 346 /ae + dup 340 /agrave + dup 345 /aring + dup 347 /ccedilla + dup 351 /eacute + dup 352 /ecircumflex + dup 353 /edieresis + dup 350 /egrave + dup 355 /iacute + dup 356 /icircumflex + dup 357 /idieresis + dup 354 /igrave + dup 360 /dcroat + dup 361 /ntilde + dup 363 /oacute + dup 364 /ocircumflex + dup 366 /odieresis + dup 362 /ograve + dup 365 /otilde + dup 370 /oslash + dup 372 /uacute + dup 373 /ucircumflex + dup 374 /udieresis + dup 371 /ugrave + dup 375 /yacute + dup 377 /ydieresis + +% Set up ISO Latin 1 character encoding +/starnetISO { + dup dup findfont dup length dict begin + { 1 index /FID ne { def }{ pop pop } ifelse + } forall + /Encoding EncodingVector def + currentdict end definefont +} def +/Times-Roman starnetISO def +/Times-Italic starnetISO def +/Times-Bold starnetISO def +/Times-BoldItalic starnetISO def +/Helvetica starnetISO def +/Helvetica-Oblique starnetISO def +/Helvetica-Bold starnetISO def +/Helvetica-BoldOblique starnetISO def +/Courier starnetISO def +/Courier-Oblique starnetISO def +/Courier-Bold starnetISO def +/Courier-BoldOblique starnetISO def +cleartomark +} bind def + +/coord-font-family /Times-Roman def +/default-font-family /Times-Roman def +/coordfont coord-font-family findfont 8 scalefont def + +/InvScaleFactor 1.0 def +/set_scale { + dup 1 exch div /InvScaleFactor exch def + dup scale +} bind def + +% styles +/solid { [] 0 setdash } bind def +/dashed { [9 InvScaleFactor mul dup ] 0 setdash } bind def +/dotted { [1 InvScaleFactor mul 6 InvScaleFactor mul] 0 setdash } bind def +/invis {/fill {newpath} def /stroke {newpath} def /show {pop newpath} def} bind def +/bold { 2 setlinewidth } bind def +/filled { } bind def +/unfilled { } bind def +/rounded { } bind def +/diagonals { } bind def + +% hooks for setting color +/nodecolor { sethsbcolor } bind def +/edgecolor { sethsbcolor } bind def +/graphcolor { sethsbcolor } bind def +/nopcolor {pop pop pop} bind def + +/beginpage { % i j npages + /npages exch def + /j exch def + /i exch def + /str 10 string def + npages 1 gt { + gsave + coordfont setfont + 0 0 moveto + (\() show i str cvs show (,) show j str cvs show (\)) show + grestore + } if +} bind def + +/set_font { + findfont exch + scalefont setfont +} def + +% draw aligned label in bounding box aligned to current point +/alignedtext { % width adj text + /text exch def + /adj exch def + /width exch def + gsave + width 0 gt { + text stringwidth pop adj mul 0 rmoveto + } if + [] 0 setdash + text show + grestore +} def + +/boxprim { % xcorner ycorner xsize ysize + 4 2 roll + moveto + 2 copy + exch 0 rlineto + 0 exch rlineto + pop neg 0 rlineto + closepath +} bind def + +/ellipse_path { + /ry exch def + /rx exch def + /y exch def + /x exch def + matrix currentmatrix + newpath + x y translate + rx ry scale + 0 0 1 0 360 arc + setmatrix +} bind def + +/endpage { showpage } bind def +/showpage { } def + +/layercolorseq + [ % layer color sequence - darkest to lightest + [0 0 0] + [.2 .8 .8] + [.4 .8 .8] + [.6 .8 .8] + [.8 .8 .8] + ] +def + +/layerlen layercolorseq length def + +/setlayer {/maxlayer exch def /curlayer exch def + layercolorseq curlayer 1 sub layerlen mod get + aload pop sethsbcolor + /nodecolor {nopcolor} def + /edgecolor {nopcolor} def + /graphcolor {nopcolor} def +} bind def + +/onlayer { curlayer ne {invis} if } def + +/onlayers { + /myupper exch def + /mylower exch def + curlayer mylower lt + curlayer myupper gt + or + {invis} if +} def + +/curlayer 0 def + +14 default-font-family set_font +1 setmiterlimit +% /arrowlength 10 def +% /arrowwidth 5 def + +% make sure pdfmark is harmless for PS-interpreters other than Distiller +/pdfmark where {pop} {userdict /pdfmark /cleartomark load put} ifelse +% make '<<' and '>>' safe on PS Level 1 devices +/languagelevel where {pop languagelevel}{1} ifelse +2 lt { + userdict (<<) cvn ([) cvn load put + userdict (>>) cvn ([) cvn load put +} if + +gsave +35 35 384 326 boxprim clip newpath +36 36 translate +0 0 1 beginpage +0 0 translate 0 rotate +0.000 0.000 0.000 graphcolor +14.00 /Times-Roman set_font + +% Top +gsave 10 dict begin +191 306 27 18 ellipse_path +stroke +gsave 10 dict begin +180 301 moveto +(Top) +[7.44 6.96 6.96] +xshow +end grestore +end grestore + +% NullableInst(object) +gsave 10 dict begin +191 234 69 18 ellipse_path +stroke +gsave 10 dict begin +134 229 moveto +(NullableInst\(object\)) +[9.84 6.96 3.84 3.84 6.24 6.96 3.84 6.24 4.56 6.96 5.28 3.84 4.56 6.96 6.96 3.84 6.24 6.24 3.84 4.56] +xshow +end grestore +end grestore + +% Top -> NullableInst(object) +newpath 191 288 moveto +191 280 191 271 191 262 curveto +stroke +gsave 10 dict begin +solid +1 setlinewidth +0.000 0.000 0.000 edgecolor +newpath 195 262 moveto +191 252 lineto +188 262 lineto +closepath +fill +0.000 0.000 0.000 edgecolor +newpath 195 262 moveto +191 252 lineto +188 262 lineto +closepath +stroke +end grestore + +% Inst(object) +gsave 10 dict begin +191 162 45 18 ellipse_path +stroke +gsave 10 dict begin +159 157 moveto +(Inst\(object\)) +[4.56 6.96 5.28 3.84 4.56 6.96 6.96 3.84 6.24 6.24 3.84 4.56] +xshow +end grestore +end grestore + +% NullableInst(object) -> Inst(object) +newpath 191 216 moveto +191 208 191 199 191 190 curveto +stroke +gsave 10 dict begin +solid +1 setlinewidth +0.000 0.000 0.000 edgecolor +newpath 195 190 moveto +191 180 lineto +188 190 lineto +closepath +fill +0.000 0.000 0.000 edgecolor +newpath 195 190 moveto +191 180 lineto +188 190 lineto +closepath +stroke +end grestore + +% NullableInst(cls1) +gsave 10 dict begin +64 162 64 18 ellipse_path +stroke +gsave 10 dict begin +13 157 moveto +(NullableInst\(cls1\)) +[9.84 6.96 3.84 3.84 6.24 6.96 3.84 6.24 4.56 6.96 5.28 3.84 4.56 6.24 3.84 5.52 6.96 4.56] +xshow +end grestore +end grestore + +% NullableInst(object) -> NullableInst(cls1) +newpath 162 217 moveto +144 207 121 194 102 183 curveto +stroke +gsave 10 dict begin +solid +1 setlinewidth +0.000 0.000 0.000 edgecolor +newpath 103 180 moveto +93 178 lineto +100 186 lineto +closepath +fill +0.000 0.000 0.000 edgecolor +newpath 103 180 moveto +93 178 lineto +100 186 lineto +closepath +stroke +end grestore + +% NullableInst(cls2) +gsave 10 dict begin +318 162 64 18 ellipse_path +stroke +gsave 10 dict begin +267 157 moveto +(NullableInst\(cls2\)) +[9.84 6.96 3.84 3.84 6.24 6.96 3.84 6.24 4.56 6.96 5.28 3.84 4.56 6.24 3.84 5.52 6.96 4.56] +xshow +end grestore +end grestore + +% NullableInst(object) -> NullableInst(cls2) +newpath 220 217 moveto +238 207 261 194 280 183 curveto +stroke +gsave 10 dict begin +solid +1 setlinewidth +0.000 0.000 0.000 edgecolor +newpath 282 186 moveto +289 178 lineto +279 180 lineto +closepath +fill +0.000 0.000 0.000 edgecolor +newpath 282 186 moveto +289 178 lineto +279 180 lineto +closepath +stroke +end grestore + +% Inst(cls1) +gsave 10 dict begin +105 90 39 18 ellipse_path +stroke +gsave 10 dict begin +78 85 moveto +(Inst\(cls1\)) +[4.56 6.96 5.28 3.84 4.56 6.24 3.84 5.52 6.96 4.56] +xshow +end grestore +end grestore + +% Inst(object) -> Inst(cls1) +newpath 171 146 moveto +159 136 144 123 132 113 curveto +stroke +gsave 10 dict begin +solid +1 setlinewidth +0.000 0.000 0.000 edgecolor +newpath 134 110 moveto +124 106 lineto +129 115 lineto +closepath +fill +0.000 0.000 0.000 edgecolor +newpath 134 110 moveto +124 106 lineto +129 115 lineto +closepath +stroke +end grestore + +% Inst(cls2) +gsave 10 dict begin +277 90 39 18 ellipse_path +stroke +gsave 10 dict begin +250 85 moveto +(Inst\(cls2\)) +[4.56 6.96 5.28 3.84 4.56 6.24 3.84 5.52 6.96 4.56] +xshow +end grestore +end grestore + +% Inst(object) -> Inst(cls2) +newpath 211 146 moveto +223 136 238 123 250 113 curveto +stroke +gsave 10 dict begin +solid +1 setlinewidth +0.000 0.000 0.000 edgecolor +newpath 253 115 moveto +258 106 lineto +248 110 lineto +closepath +fill +0.000 0.000 0.000 edgecolor +newpath 253 115 moveto +258 106 lineto +248 110 lineto +closepath +stroke +end grestore + +% Bottom +gsave 10 dict begin +191 18 34 18 ellipse_path +stroke +gsave 10 dict begin +169 13 moveto +(Bottom) +[9.36 6.72 3.84 3.84 6.96 10.8] +xshow +end grestore +end grestore + +% Inst(cls1) -> Bottom +newpath 124 74 moveto +136 64 151 51 165 40 curveto +stroke +gsave 10 dict begin +solid +1 setlinewidth +0.000 0.000 0.000 edgecolor +newpath 168 42 moveto +173 33 lineto +163 37 lineto +closepath +fill +0.000 0.000 0.000 edgecolor +newpath 168 42 moveto +173 33 lineto +163 37 lineto +closepath +stroke +end grestore + +% NullableInst(cls1) -> Inst(cls1) +newpath 74 144 moveto +78 136 84 126 90 117 curveto +stroke +gsave 10 dict begin +solid +1 setlinewidth +0.000 0.000 0.000 edgecolor +newpath 93 118 moveto +95 108 lineto +87 115 lineto +closepath +fill +0.000 0.000 0.000 edgecolor +newpath 93 118 moveto +95 108 lineto +87 115 lineto +closepath +stroke +end grestore + +% None +gsave 10 dict begin +191 90 29 18 ellipse_path +stroke +gsave 10 dict begin +175 85 moveto +(None) +[9.84 6.96 6.96 6.24] +xshow +end grestore +end grestore + +% NullableInst(cls1) -> None +newpath 93 146 moveto +113 135 140 120 160 107 curveto +stroke +gsave 10 dict begin +solid +1 setlinewidth +0.000 0.000 0.000 edgecolor +newpath 162 110 moveto +169 102 lineto +159 104 lineto +closepath +fill +0.000 0.000 0.000 edgecolor +newpath 162 110 moveto +169 102 lineto +159 104 lineto +closepath +stroke +end grestore + +% None -> Bottom +newpath 191 72 moveto +191 64 191 55 191 46 curveto +stroke +gsave 10 dict begin +solid +1 setlinewidth +0.000 0.000 0.000 edgecolor +newpath 195 46 moveto +191 36 lineto +188 46 lineto +closepath +fill +0.000 0.000 0.000 edgecolor +newpath 195 46 moveto +191 36 lineto +188 46 lineto +closepath +stroke +end grestore + +% Inst(cls2) -> Bottom +newpath 258 74 moveto +246 64 231 51 217 40 curveto +stroke +gsave 10 dict begin +solid +1 setlinewidth +0.000 0.000 0.000 edgecolor +newpath 219 37 moveto +209 33 lineto +214 42 lineto +closepath +fill +0.000 0.000 0.000 edgecolor +newpath 219 37 moveto +209 33 lineto +214 42 lineto +closepath +stroke +end grestore + +% NullableInst(cls2) -> None +newpath 289 146 moveto +269 135 242 120 222 107 curveto +stroke +gsave 10 dict begin +solid +1 setlinewidth +0.000 0.000 0.000 edgecolor +newpath 223 104 moveto +213 102 lineto +220 110 lineto +closepath +fill +0.000 0.000 0.000 edgecolor +newpath 223 104 moveto +213 102 lineto +220 110 lineto +closepath +stroke +end grestore + +% NullableInst(cls2) -> Inst(cls2) +newpath 308 144 moveto +304 136 298 126 292 117 curveto +stroke +gsave 10 dict begin +solid +1 setlinewidth +0.000 0.000 0.000 edgecolor +newpath 295 115 moveto +287 108 lineto +289 118 lineto +closepath +fill +0.000 0.000 0.000 edgecolor +newpath 295 115 moveto +287 108 lineto +289 118 lineto +closepath +stroke +end grestore +endpage +showpage +grestore +end +restore +%%Trailer +cleartomark countdictstack exch sub { end } repeat restore +%%EOF Added: pypy/extradoc/talk/dls2006/image/typesystems.eps ============================================================================== --- (empty file) +++ pypy/extradoc/talk/dls2006/image/typesystems.eps Wed May 31 14:35:47 2006 @@ -0,0 +1,1695 @@ +%!PS-Adobe-2.0 EPSF-1.2 +%%Title: lattice +%%Creator: dot version 2.2 (Tue Mar 22 18:02:44 UTC 2005) +%%CreationDate: 2006-05-31 14:21 typesystems.ps +%%For: (carlson) Carl Friedrich Bolz +%%Pages: 1 +%%DocumentFonts: +%%BoundingBox: 36 36 315 222 +%%EndComments + +%%BeginProlog +%%BeginPreview: 279 186 8 1302 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000011 +% 66888888888888888888888888888888888888888888888888888888888888888888886600000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 000000000000000000000000000000000000000000000000000000000000000000000000001188ee +% dd88888888888888888888888888888888888888888888888888888888888888888888ddee881100 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000002299eebb66 +% 00000000000000000000000000000000000000000000000000000000000000000000000066bbee99 +% 22000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 0000000000000000000000000000000000000000000000000000000000000000004499ffaa440000 +% 000000000000000000000000000000000000000000000000000000000000000000000000000044bb +% ff993300000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 0000000000000000000000000000000000000000000000000000000000000044bbff992200000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 2299ffbb440000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 000000000000000000000000000000000000000000000000000000000066ddee8822000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00002288eedd66000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000001188dddd77110000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 000000001188dddd7711000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 0000000000000000000000000000000000000000000000002288eedd660000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 0000000000000066ddee882200000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 000000000000000000000000000000000000000000002299ffbb4400000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000044bbff99220000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 000000000000000000000000000000000000000044bbff9933000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000004499ffaa44000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000066bbee99220000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 000000000000000000000000002299eebb6600000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 0000000000000000000000000000000033ddee881100000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 0000000000000000000000000000001188eedd330000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000889900000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000001199880000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000888800000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000088880000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000888800000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000022660000000000000000000000000000000000 +% 00000000000000000000000000000000000088880000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 000000000000000000000000000000008888000000000000000000000000000000bbffffffffaa33 +% 0000bbffffffee992200000000000000000000000033ff0000000000000000000000000000000000 +% 00000000000000000000000000000000000088880000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 0000000000000000000000000000000088880000000000000000000000000000000033ff001188dd +% 00000033ff001188bb00000000000000000066000000ff0000000000000000000000000000000000 +% 00000000000000000000000000000000000088880000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 0000000000000000000000000000000088880000000000000000000000000000000000ff000000ff +% 00000000ff000000ff000000000000000000dd000000ff0000000000000000000000000000000000 +% 00000000000000000000000000000000000088880000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 0000000000000000000000000000000088880000000000000000000000000000000000ff00006688 +% 00000000ff001188bb00bbffff0044ffbb88ffff8800ff88eeff88000011bbffbb110044cc99ddff +% 88000000000000000000000000000000000088880000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 0000000000000000000000000000000088880000000000000000000000000000000000ff88ee8800 +% 00000000ffffffaa110022ee550000991100ff000000ff660033ff0000aa660099aa0000ff660033 +% ff000000000000000000000000000000000088880000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 0000000000000000000000000000000088880000000000000000000000000000000000ff0099ff44 +% 00000000ff00000000000088dd0022880000ff000000ff000000ff0000ff000011ff0000ff000000 +% ff000000000000000000000000000000000088880000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 0000000000000000000000000000000088880000000000000000000000000000000000ff0011ccee +% 33000000ff00000000000011ee8899220000ff000000ff000000ff0000ff220000ff0000ff000000 +% ff000000000000000000000000000000000088880000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 0000000000000000000000000000000088880000000000000000000000000000000033ff110033ee +% ee440033ff1100000000000066ee99000000ff110011ff110011ff1100aa990077990011ff110011 +% ff110000000000000000000000000000000088880000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 000000000000000000000000000000008888000000000000000000000000000000bbffffff000066 +% ffffcdffffff44000000000000dd44000000aaff77bbffff88ffffbb0011bbffbb1100bbffff44ff +% ffbb0000000000000000000000000000000088880000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000888800000000000000000000000000000000000000000000 +% 00000000000000000000000000aa0000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000088880000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000889900000000000000000000000000000000000000000000 +% 00000000000000000000000077660000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000001199880000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 0000000000000000000000000000000033ddee881100000000000000000000000000000000000000 +% 0000000000000000000077ff88000000000000000000000000000000000000000000000000000000 +% 0000000000000000000000000000001188eedd330000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000066bbee99220000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 000000000000000000000000002299eebb6600000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 000000000000000000000000000000000000000044bbff9933000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000004499ffaa44000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 000000000000000000000000000000000000000000002299ffbb4400000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000044bbff99220000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 0000000000000000000000000000000000000000000000002288eedd660000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 0000000000000066ddee882200000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000001188dddd77110000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 000000001188dddd7711000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 000000000000000000000000000000000000000000000000000000000066ddee8822000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00002288eedd66000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 0000000000000000000000000000000000000000000000000000000000000044bbff992200000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 2299ffbb440000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 0000000000000000000000000000000000000000000000000000000000000000004499ffaa440000 +% 000000000000000000000000000000000000000000000000000000000000000000000000000044bb +% ff993300000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000002299eebb66 +% 00000000000000000000000000000000000000000000000000000000000000000000000066bbee99 +% 22000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 000000000000000000000000000000000000000000000000000000000000000000000000001188f2 +% dd88888888888888888888888888888888888888888888888888888888888888888888ddf2881100 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 000000000000000000000000000000000000000000000000000000000000000000000000000066ff +% 8f888888888888888888888888888888888888888888888888888888888888888888888fff660000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 0000000000000000000000000000000000000000000000000000000000000000000000000066ff66 +% 00000000000000000000000000000000000000000000000000000000000000000000000066ff6600 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000066ff6600 +% 0000000000000000000000000000000000000000000000000000000000000000000000000066ff66 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 000000000000000000000000000000000000000000000000000000000000000000000066ff660000 +% 000000000000000000000000000000000000000000000000000000000000000000000000000066ff +% 66000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 0000000000000000000000000000000000000000000000000000000000000000000066ff66000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000066 +% ff660000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000066ff6600000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 66ff6600000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 000000000000000000000000000000000000000000000000000000000000000066ff660000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 0066ff66000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 0000000000000000000000000000000000000000000000000000000000000066ff66000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 000066ff660000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000066ff6600000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000066ff6600000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 000000000000000000000000000000000000000000000000000000000066ff660000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 0000000066ff66000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 0000000000000000000000000000000000000000000000000000000066ff66000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 000000000066ff660000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000066ff6600000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000066ff6600000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 000000000000000000000000000000000000000000000000000066ff660000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 0000000000000066ff66000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 0000000000000000000000000000000000000000000000000066ff66000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 000000000000000066ff660000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000066ff6600000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000066ff6600000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 000000000000000000000000000000000000000000000066ff660000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 0000000000000000000066ff66000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 0000000000000000000000000000000000000000000066ff66000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 000000000000000000000066ff660000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000066ff6600000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000066ff6600000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 000000000000000000000000000000000000000066ff660000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 0000000000000000000000000066ff66000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 0000000000000000000000000000000000000066ff66000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 000000000000000000000000000066ff660000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000066ff6600000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000066ff6600000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 000000000000000000000000000000000066ff660000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 0000000000000000000000000000000066ff66000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 0000000000000000000000000000000066ff66000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 000000000000000000000000000000000066ff660000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000066ff6600000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000066ff6600000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 000000000000000000000000000066ff660000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 0000000000000000000000000000000000000066ff66000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 0000000000000000000000000066ff66000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 000000000000000000000000000000000000000066ff660000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000066ff6600000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000066ff6600000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 000000000000223300000066ff660000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 0000000000000000000000000000000000000000000066ff66000000332200000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 000000000000ebff660066ff66000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 000000000000000000000000000000000000000000000066ff660066ffeb00000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 000000000066fbffffa3ff6600000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000066ffa3fffffb66000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 0000000000ebffffffffa30000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000a3ffffffffeb000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 0000000066fbffffffffff6600000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000066fffffffffffb660000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000ebffffffffffffff55000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 000000000000000000000000000000000000000000000055ffffffffffffffeb0000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000066fbfffffffffffbeb22000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 000000000000000000000000000000000000000000000022ebfbfffffffffffb6600000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 000000ebfffffffffbeb660000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 0000000000000000000000000000000000000000000000000066ebfbffffffffeb00000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 000066fbfffffbeb6600000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000066ebfbfffffb66000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 0000ebfffbeb66000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 000000000000000000000000000000000000000000000000000000000066ebfbffeb000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000022778888 +% 88888888888888888888888888888888888888888888888888888888888888888888888888888888 +% 88b8fff6b88888888888772200000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000003377888888888888b8f6ffb88888888888 +% 88888888888888888888888888888888888888888888888888888888888888888888888888888877 +% 330000000000000000000000000000000000000000000000000000000000000000000000000000 +% 0000000000000000000000000000000000000000000000000000000000000000005588ddffbb8888 +% 88888888888888888888888888888888888888888888888888888888888888888888888888888888 +% 8890b888888888888888bbffdd884400000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000115599ddffbb8888888888888888b8908888888888 +% 888888888888888888888888888888888888888888888888888888888888888888888888888888bb +% ffdd99551100000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000001166aaeeee996611000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 0000000000000000000000116699eeeeaa6611000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 000000000000000000000000000000003388bbffdd88551100000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 115588ddffbb883300000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000003377ccffcc883300000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 0000000000000000000000000000004488ccffcc7733000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 000000000000000000000000116699eeffaa77220000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 000000002277aaffee996611000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000005599ddffaa772200000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 0000000000000000000000000000000000002277aaffdd8855000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 0000000000000000003388ccffdd8855000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000005588ddffcc8833000000000000000000000000000000000000000000000000 +% 000000000000000000000000000000000000002266aaffdd99551100000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 000000000000000000000000000000000000000000115599eeffaa66220000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000002266aaeeeeaa6622000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000002266aaeeeeaa66220000000000000000000000000000000000000000 +% 000000000000000000000000000000003388ccffcc88330000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 000000000000000000000000000000000000000000000000003388ccffcc88330000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00004488ccffcc884400000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 0000000000000000000000000000004488ccffcc88440000000000000000000000000000000000 +% 000000000000000000000000115599eeffaa66220000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 000000000000000000000000000000000000000000000000000000002266aaffdd99551100000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000002266 +% aaeeeeaa662200000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 0000000000000000000000000000000000002266aaeeeeaa662200000000000000000000000000 +% 0000000000000000002277aaffdd8855000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000005599ddffaa772200 +% 00000000000000000000000000000000000000000000000000000000000000000000005588ddffcc +% 88330000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 000000000000000000000000000000000000000000003388ccffdd885500000000000000000000 +% 0000000000004488ccffcc7733000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000003377ccffcc +% 883300000000000000000000000000000000000000000000000000000000002277aaffee99661100 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000116699eeffaa7722000000000000 +% 0000116699eeeeaa6611000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000001166 +% aaeeee996611000000000000000000000000000000000000000000115588ddffbb88330000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000003388bbffdd8855110000 +% 33bbffdd884400000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00005588ddffbb33000000000000000000000000000000000033bbffdd9955110000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 0000000000000000000000000000000000000000000000000000000000000000115599ddffbb33 +% 88aa2200000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 000000000022aa88000000000000000000000000000000000088aa33000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000033aa88 +% 88880000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000088880000000000000000000000000000000000888800000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 000000000000000000000000000000000000000000000000000000000000000000000000008888 +% 88880000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000088880000000000000000000000000000000000888800000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 000000000000000000000000000000000000000000000000000000000000000000000000008888 +% 8888000000000000000000000000000000bbffffff0000000000bbffffff0000000000000000bbff +% ffffffffffff44000000000000000000000000000000000000000000000033ddffcc884400000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000088880000000000000000000000000000000000888800000000000000000000000000 +% 00000000000033aaffffaa330000000033aaffffaa33000000000000bbffffffffffffff44000000 +% 000000000000000000000000000000000000000033ddffcc88440000000000000000000000000000 +% 000000000000000000000000000000000000000000000000000000000000000000000000008888 +% 88880000000000000000000000000000000044ff2200000000000044ff2200000000000000009922 +% 0000ff000066440000000000000000000000000000000000000000000000ee550033cc7700000000 +% 00000000000000000066000000000000000000000000000000000000000000000000000000000000 +% 00000000000088880000000000000000000000000000000000888800000000000000000000000000 +% 000000000022dd66000077dd22000022dd66000077dd22000000000099220000ff00006644000000 +% 0000000000000000000000000000000000000000ee550033cc770000000000000000000000000066 +% 000000000000000000000000000000000000000000000000000000000000000000000000008888 +% 88880000000000000000000000000000000000ff0000000000000000ff0000000000000000000000 +% 0000ff000000000000000000000000000000000000000000000000000000ee110000117700000000 +% 000000000000000000dd000000000000000000000000000000000000000000000000000000000000 +% 00000000000088880000000000000000000000000000000000888800000000000000000000000000 +% 0000000000998800000000779900009988000000007799000000000000000000ff00000000000000 +% 0000000000000000000000000000000000000000ee110000117700000000000000000000000000dd +% 000000000000000000000000000000000000000000000000000000000000000000000000008888 +% 88880000000000000000000000000000000000ff0000000000000000ff0000000000000000000000 +% 0000ff0000bbffff0044ffbb44dd99ffdd33000066ddffbb11000000000066cc4400000000bbffff +% 0044ffbb88ffff6688ffff880066ddffbb1144cc88ccffbb88eeff88000000000000000000000000 +% 00000000000088880000000000000000000000000000000000888800000000000000000000000000 +% 0000000000ee220000000011ee0000ee220000000011ee000000000000000000ff0000bbffff0044 +% ffbb44dd99ffdd33000066ddffbb11000000000066cc44000000bbffff0044ffbb0088ffff6688ff +% ff880066ddffbb1144cc88ccffbb88eeff88000000000000000000000000000000000000008888 +% 88880000000000000000000000000000000000ff0000000000000000ff0000000000000000000000 +% 0000ff000022ee550000991100ff440088cc0044ffffffff880000000000001188aa44000022ee55 +% 00009911ff22114400ff000044ffffffff8800ff550033ff440033ff000000000000000000000000 +% 00000000000088880000000000000000000000000000000000888800000000000000000000000000 +% 0000000000ff000000000000ff0000ff000000000000ff000000000000000000ff000022ee550000 +% 991100ff440088cc0044ffffffff880000000000001188aa440022ee550000991100ff22114400ff +% 000044ffffffff8800ff550033ff440033ff000000000000000000000000000000000000008888 +% 88880000000000000000000000000000000000ff0000000000000000ff0000000000000000000000 +% 0000ff00000088dd0022880000ff000011ff008877000000000000000000000000119966000088dd +% 002288005577110000ff000088770000000000ff000000ff000000ff000000000000000000000000 +% 00000000000088880000000000000000000000000000000000888800000000000000000000000000 +% 0000000000ee110000000022ee0000ee110000000022ee000000000000000000ff00000088dd0022 +% 880000ff000011ff0088770000000000000000000000001199660088dd00228800005577110000ff +% 000088770000000000ff000000ff000000ff000000000000000000000000000000000000008888 +% 88880000000000000000000000000000000000ff0000000011220000ff0000000011220000000000 +% 0000ff00000011ee8899220000ff000011ee00aa990000002200000000443300000000ff000011ee +% 889922001111776600ff0000aa990000002200ff000000ff000000ff000000000000000000000000 +% 00000000000088880000000000000000000000000000000000888800000000000000000000000000 +% 0000000000997700000000889900009977000000008899000000000000000000ff00000011ee8899 +% 220000ff000011ee00aa990000002200000000443300000000ff0011ee88992200001111776600ff +% 0000aa990000002200ff000000ff000000ff000000000000000000000000000000000000008888 +% 88880000000000000000000000000000000044ff11000022aa220044ff11000022aa220000000000 +% 0033ff2200000066ee99000000ff440088880066ff550044660000000044ee66000077dd00000066 +% ee990000990033ff00ff110066ff5500446611ff110011ff110011ff110000000000000000000000 +% 00000000000088880000000000000000000000000000000000888800000000000000000000000000 +% 000000000022dd66000077dd22000022dd66000077dd22000000000000000033ff2200000066ee99 +% 000000ff440088880066ff550044660000000044ee66000077dd000066ee99000000990033ff00ff +% 110066ff5500446611ff110011ff110011ff110000000000000000000000000000000000008888 +% 8888000000000000000000000000000000bbffffffffffffcc00bbffffffffffffcc000000000000 +% bbffffff44000000dd44000000ffddff9911000088ffee88000000000011cc55ddffaa3300000000 +% dd440000ddffee7700aaff770088ffee8800bbffff44ffffff88ffffbb0000000000000000000000 +% 00000000000088880000000000000000000000000000000000888800000000000000000000000000 +% 00000000000033aaffffaa330000000033aaffffaa330000000000000000bbffffff44000000dd44 +% 000000ffddff9911000088ffee88000000000011cc55ddffaa33000000dd44000000ddffee7700aa +% ff770088ffee8800bbffff44ffffff88ffffbb0000000000000000000000000000000000008888 +% 88880000000000000000000000000000000000000000000000000000000000000000000000000000 +% 0000000000000000aa00000000ff0000000000000000000000000000000000000000000000000000 +% aa000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000088880000000000000000000000000000000000888800000000000000000000000000 +% 0000000000000000000000000000000000000000000000000000000000000000000000000000aa00 +% 000000ff00000000000000000000000000000000000000000000000000aa00000000000000000000 +% 000000000000000000000000000000000000000000000000000000000000000000000000008888 +% 88aa2200000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000776600000011ff1100000000000000000000000000000000000000000000000077 +% 66000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 000000000022aa88000000000000000000000000000000000088aa33000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000776600 +% 000011ff110000000000000000000000000000000000000000000000776600000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000033aa88 +% 33bbffdd884400000000000000000000000000000000000000000000000000000000000000000000 +% 000000000077ff8800000000ffffff8800000000000000000000000000000000000000000077ff88 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00005588ddffbb33000000000000000000000000000000000033bbffdd9955110000000000000000 +% 000000000000000000000000000000000000000000000000000000000000000000000077ff880000 +% 0000ffffff88000000000000000000000000000000000000000077ff880000000000000000000000 +% 0000000000000000000000000000000000000000000000000000000000000000115599ddffbb33 +% 0000116699eeeeaa6611000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000001166 +% aaeeee996611000000000000000000000000000000000000000000115588ddffbb88330000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000003388bbffdd8855110000 +% 0000000000004488ccffcc7733000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000003377ccffcc +% 883300000000000000000000000000000000000000000000000000000000002277aaffee99661100 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000116699eeffaa7722000000000000 +% 0000000000000000002277aaffdd8855000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000005599ddffaa772200 +% 00000000000000000000000000000000000000000000000000000000000000000000005588ddffcc +% 88330000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 000000000000000000000000000000000000000000003388ccffdd885500000000000000000000 +% 000000000000000000000000115599eeffaa66220000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 000000000000000000000000000000000000000000000000000000002266aaffdd99551100000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000002266 +% aaeeeeaa662200000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 0000000000000000000000000000000000002266aaeeeeaa662200000000000000000000000000 +% 000000000000000000000000000000003388ccffcc88330000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 000000000000000000000000000000000000000000000000003388ccffcc88330000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00004488ccffcc884400000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 0000000000000000000000000000004488ccffcc88440000000000000000000000000000000000 +% 000000000000000000000000000000000000002266aaffdd99551100000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 000000000000000000000000000000000000000000115599eeffaa66220000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000002266aaeeeeaa6622000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000002266aaeeeeaa66220000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000005599ddffaa772200000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 0000000000000000000000000000000000002277aaffdd8855000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 0000000000000000003388ccffdd8855000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000005588ddffcc8833000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000003377ccffcc883300000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 0000000000000000000000000000004488ccffcc7733000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 000000000000000000000000116699eeffaa77220000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 000000002277aaffee996611000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000001166aaeeee996611000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 0000000000000000000000116699eeeeaa6611000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 000000000000000000000000000000003388bbffdd88551100000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 115588ddffbb883300000000000000000000000000000000000000000000000000000000000000 +% 0000000000000000000000000000000000000000000000000000000000000000005588ddffbb8888 +% 88888888888888888888888888888888888888888888888888888888888888888888888888888888 +% 88888888888888888888bbffdd884400000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000115599ddffbb888888888888888888888888888888 +% 888888888888888888888888888888888888888888888888888888888888888888888888888888bb +% ffdd99551100000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000022778888 +% 88888888888888888888888888888888888888888888888888888888888888888888888888888888 +% 88888888888888888888772200000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000003377888888888888888888888888888888 +% 88888888888888888888888888888888888888888888888888888888888888888888888888888877 +% 330000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000008888000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000008888000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000008888000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000008888000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000008888000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000008888000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000008888000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000008888000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000008888000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000008888000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000008888000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000008888000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000008888000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000008888000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000008888000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000008888000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000008888000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000008888000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000008888000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000008888000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000008888000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000008888000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000008888000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000008888000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000008888000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000008888000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 0000000000000000000000000000000000000000338888c8c8888888220000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 000000000000000000000000000000000000000077fdffffffffffff660000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 000000000000000000000000000000000000000022fffffffffffff8110000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 000000000000000000000000000000000000000000e9ffffffffffa7000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000090ffffffffff33000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000044faffffffdd00000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000f6fffffb6600000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000a7fffff81100000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 0000000000000000000000000000000000000000000066f9ffa70000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 0000000000000000000000000000000000000000000011ffff330000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000227788 +% 8888888888888888888888888888888888888888888888e6f0888888888888888888888888888888 +% 88888888888888888877220000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 000000000000000000000000000000000000000000000000000000000000000000003388ddffbb88 +% 88888888888888888888888888888888888888888888889898888888888888888888888888888888 +% 888888888888888888bbffdd88330000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 000000000000000000000000000000000000000000000000000000000000005599eeeeaa66110000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 000000000000000000001166aaeeee99550000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 0000000000000000000000000000000000000000000000000000002266aaffdd9955000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000005599ddffaa662200000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 0000000000000000000000000000000000000000000000003377ccffcc8833000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000003388ccffcc773300000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 0000000000000000000000000000000000000000004488ddffaa7722000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000002277aaffdd884400000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 0000000000000000000000000000000000116699eeee996611000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 0000000000000000000000000000000000000000000000116699eeee996611000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000002277aaffdd884400000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 0000000000000000000000000000000000000000000000000000004488ddffaa7722000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000003388ccffcc773300000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 0000000000000000000000000000000000000000000000000000000000003377ccffcc8833000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000005599ddffaa662200000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 0000000000000000000000000000000000000000000000000000000000000000002266aaffdd9955 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 000000001166aaeeee99550000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 000000000000000000000000000000000000000000000000000000000000000000000000005599ee +% eeaa6611000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 000033bbffdd88330000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 3388ddffbb3300000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 000088aa220000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000022aa8800000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00008888000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000888800000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00008888000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000227700000000002277000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000888800000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 0000888800000000000000000000000000000000bbffffffffaa3300000000000000000000000000 +% 0000000000000000000000000066660000000000001155ff000000001155ff000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000888800000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00008888000000000000000000000000000000000033ff001188dd00000000000000000000000000 +% 00000000000000000000000000bbdd0000000000000000ff000000000000ff000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000888800000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00008888000000000000000000000000000000000000ff000000ff00000000000000000000000000 +% 0000000000000000000000006633dd6600000000000000ff000000000000ff000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000888800000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00008888000000000000000000000000000000000000ff0000668800000088eeff8800bbffbb44ff +% ff8800ffbb00000000000000990088dd00000088ddffeeff000088ddffeeff0055dd44aa990066dd +% ffbb110088ffff66000088ffff660066ddffbb110088ffff66000000000000000000000000000000 +% 00000000888800000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00008888000000000000000000000000000000000000ff88ee8800000000aa0033ff0022ff440088 +% cc0000884400000000000066440011ee66008899110077ff008899110077ff0000ff00000044ffff +% ffff8800ff2211440000ff22114444ffffffff8800ff221144000000000000000000000000000000 +% 00000000888800000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00008888000000000000000000000000000000000000ff0099ff44000000001166ff000099990044 +% ff22009900000000000000ccffffffffdd00ee11000000ff00ee11000000ff0000ff000000887700 +% 00000000557711000000557711008877000000000055771100000000000000000000000000000000 +% 00000000888800000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00008888000000000000000000000000000000000000ff0011ccee330000333300ff000022ff2299 +% 88996644000000000000558800000044ff66ff11000000ff00ff11000000ff0000ff000000aa9900 +% 0000220011117766000011117766aa99000000220011117766000000000000000000000000000000 +% 00000000888800000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00008888000000000000000000000000000000000033ff110033eeee4400ee3344ff11000099dd66 +% 22ffaa00000000000011dd2200000000ccddc0bb220044ff33bbbb220044ff3311ff22000066ff55 +% 00446600990033ff0000990033ff66ff5500446600990033ff000000000000000000000000000000 +% 00000000888800000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 0000888800000000000000000000000000000000bbffffff000066ffff44aaee88dddd220022bb00 +% 009944000000000000bbffff000000bbffffffaaffff88bb4411aaffff88bb44ffffff88000088ff +% ee880000ddffee770000ddffee770088ffee880000ddffee77000000000000000000000000000000 +% 00000000888800000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00008888000000000000000000000000000000000000000000000000000000000000000000001100 +% 00110000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000888800000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 000088aa220000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000022aa8800000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 000033bbffdd88330000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 3388ddffbb3300000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 000000001166aaeeee99550000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 000000000000000000000000000000000000000000000000000000000000000000000000005599ee +% eeaa6611000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000005599ddffaa662200000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 0000000000000000000000000000000000000000000000000000000000000000002266aaffdd9955 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000003388ccffcc773300000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 0000000000000000000000000000000000000000000000000000000000003377ccffcc8833000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000002277aaffdd884400000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 0000000000000000000000000000000000000000000000000000004488ddffaa7722000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 0000000000000000000000000000000000116699eeee996611000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 0000000000000000000000000000000000000000000000116699eeee996611000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 0000000000000000000000000000000000000000004488ddffaa7722000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000002277aaffdd884400000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 0000000000000000000000000000000000000000000000003377ccffcc8833000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000003388ccffcc773300000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 0000000000000000000000000000000000000000000000000000002266aaffdd9955000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000005599ddffaa662200000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 000000000000000000000000000000000000000000000000000000000000005599eeeeaa66110000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 000000000000000000001166aaeeee99550000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 000000000000000000000000000000000000000000000000000000000000000000003388ddffbb88 +% 88888888888888888888888888888888888888888888888888888888888888888888888888888888 +% 888888888888888888bbffdd88330000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000227788 +% 88888888888888888888888888888888888888888888888888888888888888888888888888888888 +% 88888888888888888877220000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 00000000000000000000000000000000000000000000000000000000000000000000000000000000 +% 000000000000000000000000000000000000000000000000000000000000000000000000000000 +%%EndImage +%%EndPreview +save countdictstack mark newpath /showpage {} def /setpagedevice {pop} def +%%EndProlog +%%Page 1 1 +save +/DotDict 200 dict def +DotDict begin + +/setupLatin1 { +mark +/EncodingVector 256 array def + EncodingVector 0 + +ISOLatin1Encoding 0 255 getinterval putinterval + +EncodingVector + dup 306 /AE + dup 301 /Aacute + dup 302 /Acircumflex + dup 304 /Adieresis + dup 300 /Agrave + dup 305 /Aring + dup 303 /Atilde + dup 307 /Ccedilla + dup 311 /Eacute + dup 312 /Ecircumflex + dup 313 /Edieresis + dup 310 /Egrave + dup 315 /Iacute + dup 316 /Icircumflex + dup 317 /Idieresis + dup 314 /Igrave + dup 334 /Udieresis + dup 335 /Yacute + dup 376 /thorn + dup 337 /germandbls + dup 341 /aacute + dup 342 /acircumflex + dup 344 /adieresis + dup 346 /ae + dup 340 /agrave + dup 345 /aring + dup 347 /ccedilla + dup 351 /eacute + dup 352 /ecircumflex + dup 353 /edieresis + dup 350 /egrave + dup 355 /iacute + dup 356 /icircumflex + dup 357 /idieresis + dup 354 /igrave + dup 360 /dcroat + dup 361 /ntilde + dup 363 /oacute + dup 364 /ocircumflex + dup 366 /odieresis + dup 362 /ograve + dup 365 /otilde + dup 370 /oslash + dup 372 /uacute + dup 373 /ucircumflex + dup 374 /udieresis + dup 371 /ugrave + dup 375 /yacute + dup 377 /ydieresis + +% Set up ISO Latin 1 character encoding +/starnetISO { + dup dup findfont dup length dict begin + { 1 index /FID ne { def }{ pop pop } ifelse + } forall + /Encoding EncodingVector def + currentdict end definefont +} def +/Times-Roman starnetISO def +/Times-Italic starnetISO def +/Times-Bold starnetISO def +/Times-BoldItalic starnetISO def +/Helvetica starnetISO def +/Helvetica-Oblique starnetISO def +/Helvetica-Bold starnetISO def +/Helvetica-BoldOblique starnetISO def +/Courier starnetISO def +/Courier-Oblique starnetISO def +/Courier-Bold starnetISO def +/Courier-BoldOblique starnetISO def +cleartomark +} bind def + +/coord-font-family /Times-Roman def +/default-font-family /Times-Roman def +/coordfont coord-font-family findfont 8 scalefont def + +/InvScaleFactor 1.0 def +/set_scale { + dup 1 exch div /InvScaleFactor exch def + dup scale +} bind def + +% styles +/solid { [] 0 setdash } bind def +/dashed { [9 InvScaleFactor mul dup ] 0 setdash } bind def +/dotted { [1 InvScaleFactor mul 6 InvScaleFactor mul] 0 setdash } bind def +/invis {/fill {newpath} def /stroke {newpath} def /show {pop newpath} def} bind def +/bold { 2 setlinewidth } bind def +/filled { } bind def +/unfilled { } bind def +/rounded { } bind def +/diagonals { } bind def + +% hooks for setting color +/nodecolor { sethsbcolor } bind def +/edgecolor { sethsbcolor } bind def +/graphcolor { sethsbcolor } bind def +/nopcolor {pop pop pop} bind def + +/beginpage { % i j npages + /npages exch def + /j exch def + /i exch def + /str 10 string def + npages 1 gt { + gsave + coordfont setfont + 0 0 moveto + (\() show i str cvs show (,) show j str cvs show (\)) show + grestore + } if +} bind def + +/set_font { + findfont exch + scalefont setfont +} def + +% draw aligned label in bounding box aligned to current point +/alignedtext { % width adj text + /text exch def + /adj exch def + /width exch def + gsave + width 0 gt { + text stringwidth pop adj mul 0 rmoveto + } if + [] 0 setdash + text show + grestore +} def + +/boxprim { % xcorner ycorner xsize ysize + 4 2 roll + moveto + 2 copy + exch 0 rlineto + 0 exch rlineto + pop neg 0 rlineto + closepath +} bind def + +/ellipse_path { + /ry exch def + /rx exch def + /y exch def + /x exch def + matrix currentmatrix + newpath + x y translate + rx ry scale + 0 0 1 0 360 arc + setmatrix +} bind def + +/endpage { showpage } bind def +/showpage { } def + +/layercolorseq + [ % layer color sequence - darkest to lightest + [0 0 0] + [.2 .8 .8] + [.4 .8 .8] + [.6 .8 .8] + [.8 .8 .8] + ] +def + +/layerlen layercolorseq length def + +/setlayer {/maxlayer exch def /curlayer exch def + layercolorseq curlayer 1 sub layerlen mod get + aload pop sethsbcolor + /nodecolor {nopcolor} def + /edgecolor {nopcolor} def + /graphcolor {nopcolor} def +} bind def + +/onlayer { curlayer ne {invis} if } def + +/onlayers { + /myupper exch def + /mylower exch def + curlayer mylower lt + curlayer myupper gt + or + {invis} if +} def + +/curlayer 0 def + +14 default-font-family set_font +1 setmiterlimit +% /arrowlength 10 def +% /arrowwidth 5 def + +% make sure pdfmark is harmless for PS-interpreters other than Distiller +/pdfmark where {pop} {userdict /pdfmark /cleartomark load put} ifelse +% make '<<' and '>>' safe on PS Level 1 devices +/languagelevel where {pop languagelevel}{1} ifelse +2 lt { + userdict (<<) cvn ([) cvn load put + userdict (>>) cvn ([) cvn load put +} if + +gsave +35 35 280 188 boxprim clip newpath +36 36 translate +0 0 1 beginpage +0 0 translate 0 rotate +0.000 0.000 0.000 graphcolor +14.00 /Times-Roman set_font + +% RPython +gsave 10 dict begin +newpath 179 160 moveto +179 174 lineto +155 185 lineto +121 185 lineto +97 174 lineto +97 160 lineto +121 149 lineto +155 149 lineto +closepath +stroke +gsave 10 dict begin +113 162 moveto +(RPython) +[9.36 7.68 6.96 4.08 6.96 6.96 6.96] +xshow +end grestore +end grestore + +% LL Type System +gsave 10 dict begin +newpath 127 86 moveto +127 100 lineto +90 111 lineto +38 111 lineto +1 100 lineto +1 86 lineto +38 75 lineto +90 75 lineto +closepath +stroke +gsave 10 dict begin +17 88 moveto +(LL Type System) +[8.64 8.64 3.6 7.2 6.96 6.96 6.24 3.6 7.68 6.48 5.28 3.84 6.24 10.8] +xshow +end grestore +end grestore + +% RPython -> LL Type System +newpath 120 149 moveto +111 140 100 129 89 118 curveto +stroke +gsave 10 dict begin +solid +1 setlinewidth +0.000 0.000 0.000 edgecolor +newpath 92 116 moveto +82 111 lineto +87 121 lineto +closepath +fill +0.000 0.000 0.000 edgecolor +newpath 92 116 moveto +82 111 lineto +87 121 lineto +closepath +stroke +end grestore + +% OO Type System +gsave 10 dict begin +newpath 278 86 moveto +278 100 lineto +239 111 lineto +185 111 lineto +146 100 lineto +146 86 lineto +185 75 lineto +239 75 lineto +closepath +stroke +gsave 10 dict begin +164 88 moveto +(OO Type System) +[10.08 10.08 3.6 7.2 6.96 6.96 6.24 3.6 7.68 6.48 5.28 3.84 6.24 10.8] +xshow +end grestore +end grestore + +% RPython -> OO Type System +newpath 156 149 moveto +165 140 176 129 187 118 curveto +stroke +gsave 10 dict begin +solid +1 setlinewidth +0.000 0.000 0.000 edgecolor +newpath 189 121 moveto +194 111 lineto +184 116 lineto +closepath +fill +0.000 0.000 0.000 edgecolor +newpath 189 121 moveto +194 111 lineto +184 116 lineto +closepath +stroke +end grestore + +% Raw Addresses +gsave 10 dict begin +newpath 125 12 moveto +125 26 lineto +89 37 lineto +39 37 lineto +3 26 lineto +3 12 lineto +39 1 lineto +89 1 lineto +closepath +stroke +gsave 10 dict begin +20 14 moveto +(Raw Addresses) +[9.36 5.76 10.08 3.6 9.6 6.96 6.96 4.56 6.24 5.52 5.52 6.24 5.52] +xshow +end grestore +end grestore + +% LL Type System -> Raw Addresses +newpath 64 74 moveto +64 66 64 56 64 47 curveto +stroke +gsave 10 dict begin +solid +1 setlinewidth +0.000 0.000 0.000 edgecolor +newpath 68 47 moveto +64 37 lineto +61 47 lineto +closepath +fill +0.000 0.000 0.000 edgecolor +newpath 68 47 moveto +64 37 lineto +61 47 lineto +closepath +stroke +end grestore +endpage +showpage +grestore +end +restore +%%Trailer +cleartomark countdictstack exch sub { end } repeat restore +%%EOF Modified: pypy/extradoc/talk/dls2006/paper.tex ============================================================================== --- pypy/extradoc/talk/dls2006/paper.tex (original) +++ pypy/extradoc/talk/dls2006/paper.tex Wed May 31 14:35:47 2006 @@ -351,7 +351,7 @@ \begin{figure} \centering -\includegraphics[scale=0.667]{image/typesystems.pdf} +\epsfig{file=image/typesystems.eps, scale=0.667} \caption{type systems; the arrows are transformations.} \label{fig_typesystems} \end{figure} @@ -513,7 +513,7 @@ \begin{figure*} \centering -\includegraphics[scale=0.75]{image/flowlattice.pdf} +\epsfig{file=image/flowlattice.eps, scale=0.65} \caption{The lattice order of the flow object space} \label{flowlattice} \end{figure*} @@ -688,14 +688,14 @@ \begin{figure*} \centering -\includegraphics[scale=0.75]{image/lattice1.pdf} +\epsfig{file=image/lattice1.eps, scale=0.75} \caption{The overall lattice} \label{latticeoverall} \end{figure*} \begin{figure*} \centering -\includegraphics[scale=0.75]{image/lattice2.pdf} +\epsfig{file=image/lattice2.eps, scale=0.75} \caption{The part about instances and nullable instances, assuming a simple class hierarchy with only two direct subclasses of \texttt{object}.} From cfbolz at codespeak.net Wed May 31 14:39:11 2006 From: cfbolz at codespeak.net (cfbolz at codespeak.net) Date: Wed, 31 May 2006 14:39:11 +0200 (CEST) Subject: [pypy-svn] r27977 - in pypy/extradoc/talk/dls2006: . image Message-ID: <20060531123911.D3AF010060@code0.codespeak.net> Author: cfbolz Date: Wed May 31 14:39:10 2006 New Revision: 27977 Removed: pypy/extradoc/talk/dls2006/image/flowlattice.eps pypy/extradoc/talk/dls2006/image/lattice1.eps pypy/extradoc/talk/dls2006/image/lattice2.eps pypy/extradoc/talk/dls2006/image/typesystems.eps Modified: pypy/extradoc/talk/dls2006/paper.tex Log: it seems we really want pdf Modified: pypy/extradoc/talk/dls2006/paper.tex ============================================================================== --- pypy/extradoc/talk/dls2006/paper.tex (original) +++ pypy/extradoc/talk/dls2006/paper.tex Wed May 31 14:39:10 2006 @@ -351,7 +351,7 @@ \begin{figure} \centering -\epsfig{file=image/typesystems.eps, scale=0.667} +\includegraphics[scale=0.667]{image/typesystems.pdf} \caption{type systems; the arrows are transformations.} \label{fig_typesystems} \end{figure} @@ -513,7 +513,7 @@ \begin{figure*} \centering -\epsfig{file=image/flowlattice.eps, scale=0.65} +\includegraphics[scale=0.75]{image/flowlattice.pdf} \caption{The lattice order of the flow object space} \label{flowlattice} \end{figure*} @@ -688,14 +688,14 @@ \begin{figure*} \centering -\epsfig{file=image/lattice1.eps, scale=0.75} +\includegraphics[scale=0.75]{image/lattice1.pdf} \caption{The overall lattice} \label{latticeoverall} \end{figure*} \begin{figure*} \centering -\epsfig{file=image/lattice2.eps, scale=0.75} +\includegraphics[scale=0.75]{image/lattice2.pdf} \caption{The part about instances and nullable instances, assuming a simple class hierarchy with only two direct subclasses of \texttt{object}.} From bea at codespeak.net Wed May 31 14:58:44 2006 From: bea at codespeak.net (bea at codespeak.net) Date: Wed, 31 May 2006 14:58:44 +0200 (CEST) Subject: [pypy-svn] r27978 - pypy/extradoc/talk/ep2006 Message-ID: <20060531125844.2240F1005A@code0.codespeak.net> Author: bea Date: Wed May 31 14:58:42 2006 New Revision: 27978 Added: pypy/extradoc/talk/ep2006/abstract_methodtalk.txt (contents, props changed) Log: abstract for method talk at europython Added: pypy/extradoc/talk/ep2006/abstract_methodtalk.txt ============================================================================== --- (empty file) +++ pypy/extradoc/talk/ep2006/abstract_methodtalk.txt Wed May 31 14:58:42 2006 @@ -0,0 +1,16 @@ +Abstract for Agile track at Europython 2006 +-------------------------------------------- + +Kill -9: process refactoring in the PyPy project +============================= + +In this talk we will present the experiences of running a collaborative +OSS project within a EU-funded consortium structure. We will briefly present +the initial decision process for integrating the community and the commercial +aspects of the PyPy project. We will show how agile practices within the +development team, primarily sprint-driven methodology resulted in a need for +process refactoring and how a new agile management approach was +implemented. We will spice up the analysis of the main drivers behind this +change by refererring to Hershey-Blanchards Situational Leadership model. + +Author: Beatrice D?ring \ No newline at end of file From pedronis at codespeak.net Wed May 31 15:08:28 2006 From: pedronis at codespeak.net (pedronis at codespeak.net) Date: Wed, 31 May 2006 15:08:28 +0200 (CEST) Subject: [pypy-svn] r27979 - pypy/extradoc/talk/dls2006 Message-ID: <20060531130828.7D64D1005A@code0.codespeak.net> Author: pedronis Date: Wed May 31 15:08:27 2006 New Revision: 27979 Modified: pypy/extradoc/talk/dls2006/paper.bib Log: more bib entries Modified: pypy/extradoc/talk/dls2006/paper.bib ============================================================================== --- pypy/extradoc/talk/dls2006/paper.bib (original) +++ pypy/extradoc/talk/dls2006/paper.bib Wed May 31 15:08:27 2006 @@ -182,3 +182,24 @@ url = {http://codespeak.net/pypy/dist/pypy/doc/architecture.html}, howpuplished = {Web page} } + + +% Boehm + at article{52202, + author = {Hans-Juergen Boehm and Mark Weiser}, + title = {Garbage collection in an uncooperative environment}, + journal = {Softw. Pract. Exper.}, + volume = {18}, + number = {9}, + year = {1988}, + issn = {0038-0644}, + pages = {807--820}, + publisher = {John Wiley \& Sons, Inc.}, + address = {New York, NY, USA}, + } + + + at misc{graphviz, +url = "http://www.graphviz.org/", +organization = "AT&T", +} \ No newline at end of file From cfbolz at codespeak.net Wed May 31 15:21:10 2006 From: cfbolz at codespeak.net (cfbolz at codespeak.net) Date: Wed, 31 May 2006 15:21:10 +0200 (CEST) Subject: [pypy-svn] r27981 - pypy/extradoc/talk/dls2006 Message-ID: <20060531132110.B780810063@code0.codespeak.net> Author: cfbolz Date: Wed May 31 15:21:09 2006 New Revision: 27981 Modified: pypy/extradoc/talk/dls2006/paper.bib pypy/extradoc/talk/dls2006/paper.tex Log: first round add doing real citations Modified: pypy/extradoc/talk/dls2006/paper.bib ============================================================================== --- pypy/extradoc/talk/dls2006/paper.bib (original) +++ pypy/extradoc/talk/dls2006/paper.bib Wed May 31 15:21:09 2006 @@ -88,7 +88,7 @@ } % Jikes - at inproceedings{Jikes-GC, + at inproceedings{JikesGC, author = {Stephen M. Blackburn and Perry Cheng and Kathryn S. McKinley}, Modified: pypy/extradoc/talk/dls2006/paper.tex ============================================================================== --- pypy/extradoc/talk/dls2006/paper.tex (original) +++ pypy/extradoc/talk/dls2006/paper.tex Wed May 31 15:21:09 2006 @@ -127,7 +127,7 @@ sequel, other than mention that it is written in RPython and can thus be translated. At close to 90,000 lines of code, it is the largest RPython program that we have translated so far. More information can be found -in [S]. +in \cite{A}. \section{System programming in Python} @@ -207,7 +207,7 @@ transformation step produces flow graphs that also assume automatic memory management. Generating C code directly from there produces a fully leaking program, unless we link it with an external garbage -collector (GC) like the Boehm conservative GC [Boehm], which is a +collector (GC) like the Boehm conservative GC \cite{Boehm}, which is a viable option. We have two alternatives, each implemented as a transformation step. @@ -252,7 +252,7 @@ much code in common, to convert the more Python-specific features like its complex calling conventions. -More information about these transformations can be found in [T]. +More information about these transformations can be found in \cite{T}. \subsection{System code} @@ -567,8 +567,8 @@ operations form a graph, which is the control flow graph of the original bytecode. -Note that we produce flow graphs in Static Single Information (SSI) -form, an extension of Static Single Assignment ([SSA]): each variable is +Note that we produce flow graphs in Static Single Information (SSI, \cite{SSI}) +form, an extension of Static Single Assignment (\cite{SSA}): each variable is only used in exactly one basic block. All variables that are not dead at the end of a basic block are explicitly carried over to the next block and renamed. @@ -576,7 +576,7 @@ While the Flow Object Space is quite a short piece of code -- its core functionality holds in 300 lines -- the detail of the interactions sketched above is not entierely straightforward; we refer the reader to -[D] for more information. +\cite{D} for more information. \subsection{The Annotator} @@ -1119,7 +1119,7 @@ viable for Scheme as base language. Simplicity and portability across C platforms were its major goals. -Squeak [Squeak] is a Smalltalk implementation in Smalltalk. It uses SLang, a +Squeak \cite{Squeak} is a Smalltalk implementation in Smalltalk. It uses SLang, a very restricted subset of Smalltalk with few types and strict conventions, which can be mostly directly translated to C. The VM, the object memory and the garbage collector support are @@ -1127,7 +1127,7 @@ portability were the major goals, as opposed to sophisticated manipulation and analysis or "weaving" in of features as transformation aspects. -Jikes RVM [DBLP:journals/ibmsj/AlpernABBCCCFGHHLLMNRSSSSSSW00] is a +Jikes RVM \cite{DBLP:journals/ibmsj/AlpernABBCCCFGHHLLMNRSSSSSSW00} is a Java VM and Just-In-Time compiler written in Java. Bootstrapping happens by self-applying the compiler on a host VM, and dumping a snapshot from memory of the resulting native code. @@ -1137,12 +1137,12 @@ normal software modularity. The indirection costs are taken care of by the compiler performing inlining (which is sometimes even explicitly requested). In particular this modular approach is used -for implementing a range of choices for GC support [Jikes-GC]. This was +for implementing a range of choices for GC support \cite{JikesGC}. This was the inspiration for PyPy's own GC framework, although much more tuning and work went into Jikes RVM. PyPy's own GC framework also exploits inlining of helpers and barriers to recover performance. -Jikes RVM's native JIT compilers [Jikes-JIT] +Jikes RVM's native JIT compilers \cite{Jikes-JIT} are not meant to be retargetted to run in other environments that hardware processors, for example in a CLR/.NET runtime. Also Jikes RVM pays the complexity of writing @@ -1190,7 +1190,7 @@ tool-chain itself -- a one-time effort. Dynamic languages enable the definition of multiple custom type systems, -similar to \textit{pluggable type systems} in [Bracha] but with simple +similar to \textit{pluggable type systems} in \cite{PlugType} but with simple type inference instead of explicit annotations. This proved a key feature in implementing our translation tool-chain, because it makes a many-levels approach convenient: each abstraction level can provide an From pedronis at codespeak.net Wed May 31 15:23:15 2006 From: pedronis at codespeak.net (pedronis at codespeak.net) Date: Wed, 31 May 2006 15:23:15 +0200 (CEST) Subject: [pypy-svn] r27982 - pypy/extradoc/talk/dls2006 Message-ID: <20060531132315.C87F010063@code0.codespeak.net> Author: pedronis Date: Wed May 31 15:23:13 2006 New Revision: 27982 Modified: pypy/extradoc/talk/dls2006/paper.bib Log: title for graphviz, boehm gc as software Modified: pypy/extradoc/talk/dls2006/paper.bib ============================================================================== --- pypy/extradoc/talk/dls2006/paper.bib (original) +++ pypy/extradoc/talk/dls2006/paper.bib Wed May 31 15:23:13 2006 @@ -198,8 +198,14 @@ address = {New York, NY, USA}, } + at misc{boehm-softw, +author = "Hans Boehm", +title = "A garbage collector for C and C++", +url = "http://www.hpl.hp.com/personal/Hans_Boehm/gc/" +} @misc{graphviz, url = "http://www.graphviz.org/", +title = "Graphviz - Graph Visualization Software", organization = "AT&T", -} \ No newline at end of file +} From pedronis at codespeak.net Wed May 31 15:28:10 2006 From: pedronis at codespeak.net (pedronis at codespeak.net) Date: Wed, 31 May 2006 15:28:10 +0200 (CEST) Subject: [pypy-svn] r27983 - pypy/extradoc/talk/dls2006 Message-ID: <20060531132810.A6A8610063@code0.codespeak.net> Author: pedronis Date: Wed May 31 15:28:09 2006 New Revision: 27983 Modified: pypy/extradoc/talk/dls2006/paper.tex Log: dhrystone 2.0 take care of last XXX Modified: pypy/extradoc/talk/dls2006/paper.tex ============================================================================== --- pypy/extradoc/talk/dls2006/paper.tex (original) +++ pypy/extradoc/talk/dls2006/paper.tex Wed May 31 15:28:09 2006 @@ -308,13 +308,15 @@ \label{fig_llappend} \end{figure} -In the example of the \texttt{malloc} operation, replaced by a call to GC -code, this GC code can invoke a complete collection of dead objects, and -can thus be arbitrarily complicated. Still, our GC code is entirely -written in plain Python, and it manipulates "objects" that are still at -a lower level: pointer and address objects. Even with the restriction -of having to use pointer-like and address-like objects, Python remains -more expressive than, say, C to write a GC. [XXX see also Jikes] +In the example of the \texttt{malloc} operation, replaced by a call to +GC code, this GC code can invoke a complete collection of dead +objects, and can thus be arbitrarily complicated. Still, our GC code +is entirely written in plain Python, and it manipulates "objects" that +are still at a lower level: pointer and address objects. Even with +the restriction of having to use pointer-like and address-like +objects, Python remains more expressive than, say, C to write a GC +(Jikes RVM's GC work \cite{JikesGC} was the inspiration to try to +express GCs in Python, see \ref{relatedwork}). In the sequel, we will call \textit{system code} functions written in Python that are meant to be analysed by the front-end. For the @@ -910,7 +912,7 @@ The tool-chain has been tested with and can sucessfully apply transformations enabling various combinations of features. The -translated interpreters are benchmarked using pystone (a [Dhrystone] +translated interpreters are benchmarked using pystone (a [Dhrystone] 2.0 derivative traditionally used by the Python community, although it is a rather poor benchmark) and the classical [Richards] benchmark and compared against [CPython] 2.4.3 results and are summarized in table From fijal at codespeak.net Wed May 31 15:30:33 2006 From: fijal at codespeak.net (fijal at codespeak.net) Date: Wed, 31 May 2006 15:30:33 +0200 (CEST) Subject: [pypy-svn] r27984 - pypy/dist/pypy/translator/js2 Message-ID: <20060531133033.E261710063@code0.codespeak.net> Author: fijal Date: Wed May 31 15:30:32 2006 New Revision: 27984 Modified: pypy/dist/pypy/translator/js2/database.py Log: Stupid bugfix. Modified: pypy/dist/pypy/translator/js2/database.py ============================================================================== --- pypy/dist/pypy/translator/js2/database.py (original) +++ pypy/dist/pypy/translator/js2/database.py Wed May 31 15:30:32 2006 @@ -93,6 +93,7 @@ if retval == 'name': return self.consts[const] else: + self.consts[const] return const except KeyError: log("New const:%r"%value) @@ -135,6 +136,7 @@ const.depends = None all_c.append(i) + log("Consts: %r"%self.consts) # We need to keep track of fields to make sure # our items appear earlier than us for const,name in generate_constants(self.consts): @@ -320,18 +322,3 @@ def init_fields(self, ilasm, const_var, name): pass -## ilasm.new('instance void class %s::.ctor()' % classdef._name) -## while classdef is not None: -## for name, (type_, default) in classdef._fields.iteritems(): -## if isinstance(type_, ootype.StaticMethod): -## continue -## elif type_ is ootype.Class: -## value = getattr(self.obj, name) -## self.cts.lltype_to_cts(value._INSTANCE) # force scheduling class generation -## classname = value._INSTANCE._name -## ilasm.opcode('dup') -## ilasm.opcode('ldtoken', classname) -## ilasm.call('class [mscorlib]System.Type class [mscorlib]System.Type::GetTypeFromHandle(valuetype [mscorlib]System.RuntimeTypeHandle)') -## ilasm.opcode('stfld class [mscorlib]System.Type %s::%s' % (classdef._name, name)) -## classdef = classdef._superclass -## From arigo at codespeak.net Wed May 31 15:31:39 2006 From: arigo at codespeak.net (arigo at codespeak.net) Date: Wed, 31 May 2006 15:31:39 +0200 (CEST) Subject: [pypy-svn] r27985 - pypy/extradoc/talk/dls2006 Message-ID: <20060531133139.3AF0C10064@code0.codespeak.net> Author: arigo Date: Wed May 31 15:31:37 2006 New Revision: 27985 Modified: pypy/extradoc/talk/dls2006/paper.tex Log: Move the footnote numbers after the "," or "." or ":". Modified: pypy/extradoc/talk/dls2006/paper.tex ============================================================================== --- pypy/extradoc/talk/dls2006/paper.tex (original) +++ pypy/extradoc/talk/dls2006/paper.tex Wed May 31 15:31:37 2006 @@ -145,10 +145,10 @@ written in Python and analysed with the suitable type system. The front-end part of the translation process analyses the input -RPython program in two phases, as follows\footnote{Note that the two +RPython program in two phases, as follows:\footnote{Note that the two phases are intermingled in time, because type inference proceeds from an entry point function and follows all calls, and thus only gradually -discovers (the reachable parts of) the input program.}: +discovers (the reachable parts of) the input program.} \begin{verbatim} :: @@ -159,7 +159,7 @@ \end{verbatim} % \begin{enumerate} -\item We take as input RPython functions\footnote{The input to our +\item We take as input RPython functions,\footnote{The input to our translation chain are indeed loaded runtime function objects, not source code or ASTs. This allows us to use unrestricted python for meta-programming purposes at load time, in a @@ -167,7 +167,7 @@ the source program -- as Python program -- produces the RPython program input to the tool-chain as the object graph loaded in memory. This includes both the relevant functions and prebuilt - data.}, and convert them to control flow graphs -- a structure + data.} and convert them to control flow graphs -- a structure amenable to analysis. These flow graphs contain polymorphic operations only: in Python, almost all operations are dynamically overloaded by type. @@ -286,12 +286,12 @@ This function is inserted by the LLTyper, as a helper to implement the \texttt{list.append()} calls found in its RPython-level input graphs. By going through the front-end reconfigured to use C-level types, the -above function becomes a graph with such C-level types\footnote{The +above function becomes a graph with such C-level types,\footnote{The low-level type system specifies that the function should be specialized by the C-level type of its input arguments, so it actually turns into one graph per list type -- list of integers, list of pointers, etc. This behavior gives the programmer a feeling -comparable to C++ templates, without the declarations.}, which is then +comparable to C++ templates, without the declarations.} which is then indistinguishable from the other graphs of the forest produced by the LLTyper. @@ -339,11 +339,11 @@ a way that makes sense to that level. The key reason why this is not burdensome is that the lower level implementations are also written in Python -- with the only difference that they use (and have to be -typeable in) the lower-level type system\footnote{This is not strictly +typeable in) the lower-level type system.\footnote{This is not strictly true: the type systems are even allowed to co-exist in the same function. The operations involving higher-level type systems are turned into lower-level operations by the previous transformations in -the chain, which leave the already-low-level operations untouched.}. +the chain, which leave the already-low-level operations untouched.} \subsection{Type systems} @@ -530,13 +530,13 @@ In conjunction with the Flow Object Space, the bytecode interpreter of PyPy thus performs abstract interpretation of Python bytecodes from -the application\footnote{Note that this process uses the +the application.\footnote{Note that this process uses the \textit{unmodified} bytecode interpreter. This means that it is independent of most language details. Changes in syntax or in bytecode format or opcode semantics only need to be implemented once, in the bytecode interpreter. In effect, the Flow Object Space enables an interpreter for \textit{any} language to work as a front-end for -the rest of the tool-chain.}. In this case, the bytecodes in +the rest of the tool-chain.} In this case, the bytecodes in question come from the RPython application that we would like to translate. @@ -548,7 +548,7 @@ results. The Constants serve two purposes: they are a way to introduce constant values into the flow graphs -- these values may be arbitrarily complex objects, not just primitives -- and they allow -basic constant propagation\footnote{This is useful at this level for +basic constant propagation.\footnote{This is useful at this level for some constructs of the bytecode interpreter, which can temporarily wrap internal values and push them onto the regular value stack among the other application-level objects. We need to be able to unwrap @@ -817,8 +817,9 @@ % Although the type of \texttt{x} may be some parent class of \texttt{MyClass}, it can be deduced to be of the more precise type -$Inst(MyClass)$ within the positive branch of the \texttt{if}. -\footnote{Remember that our graphs are in SSI form, which means that the +$Inst(MyClass)$ within the positive branch of the +\texttt{if}.\footnote{Remember that our graphs are in SSI form, +which means that the \texttt{x} inside each basic block is a different Variable with a possibly different type as annotation. Given that our type inference is not flow-sensitive, SSI gives an advantage over SSA here.} From bea at codespeak.net Wed May 31 15:31:45 2006 From: bea at codespeak.net (bea at codespeak.net) Date: Wed, 31 May 2006 15:31:45 +0200 (CEST) Subject: [pypy-svn] r27986 - pypy/extradoc/talk/ep2006 Message-ID: <20060531133145.7F8F010063@code0.codespeak.net> Author: bea Date: Wed May 31 15:31:41 2006 New Revision: 27986 Modified: pypy/extradoc/talk/ep2006/abstract_methodtalk.txt Log: change of title - my linux command knowledge was too crude ;-) Modified: pypy/extradoc/talk/ep2006/abstract_methodtalk.txt ============================================================================== --- pypy/extradoc/talk/ep2006/abstract_methodtalk.txt (original) +++ pypy/extradoc/talk/ep2006/abstract_methodtalk.txt Wed May 31 15:31:41 2006 @@ -1,7 +1,7 @@ Abstract for Agile track at Europython 2006 -------------------------------------------- -Kill -9: process refactoring in the PyPy project +Kill -1: process refactoring in the PyPy project ============================= In this talk we will present the experiences of running a collaborative From fijal at codespeak.net Wed May 31 15:43:55 2006 From: fijal at codespeak.net (fijal at codespeak.net) Date: Wed, 31 May 2006 15:43:55 +0200 (CEST) Subject: [pypy-svn] r27987 - in pypy/dist/pypy/translator/js2: . test Message-ID: <20060531134355.7071510068@code0.codespeak.net> Author: fijal Date: Wed May 31 15:43:54 2006 New Revision: 27987 Modified: pypy/dist/pypy/translator/js2/asmgen.py pypy/dist/pypy/translator/js2/function.py pypy/dist/pypy/translator/js2/test/test_snippet.py Log: Added variable declaration support (to avoid populating global variable space). Modified: pypy/dist/pypy/translator/js2/asmgen.py ============================================================================== --- pypy/dist/pypy/translator/js2/asmgen.py (original) +++ pypy/dist/pypy/translator/js2/asmgen.py Wed May 31 15:43:54 2006 @@ -154,7 +154,11 @@ #def field(self, f_name, cts_type): # pass - + + def set_locals(self, loc_string): + if loc_string != '': + self.codegenerator.writeline("var %s;"%loc_string) + def set_static_field(self, _type, namespace, _class, varname): self.codegenerator.writeline("%s.prototype.%s = %s;"%(_class, varname, self.right_hand.pop())) Modified: pypy/dist/pypy/translator/js2/function.py ============================================================================== --- pypy/dist/pypy/translator/js2/function.py (original) +++ pypy/dist/pypy/translator/js2/function.py Wed May 31 15:43:54 2006 @@ -150,30 +150,10 @@ self.ilasm.begin_function(self.name, args) log("loops: %r"%self.loops) + # render all variables + + self.ilasm.set_locals(",".join(self.locals)) self.render_block(self.graph.startblock) -## if self._is_return_block(block): -## return_blocks.append(block) -## continue -## -## for op in block.operations: -## self._render_op(op) -## -## for link in block.exits: -## target_label = self._get_block_name(link.target) -## if link.exitcase is None: -## pass -## self.ilasm.branch(target_label) -## else: -## assert type(link.exitcase is bool) -## assert block.exitswitch is not None -## self.ilasm.branch_if( block.exitswitch, link.exitcase, target_label) -## self._setup_link(link) - -## for block in return_blocks: -## return_var = block.inputargs[0] -## if return_var.concretetype is not Void: -## self.load(return_var) -## self.ilasm.ret() self.ilasm.end_function() if self.is_method: @@ -192,6 +172,7 @@ def _set_locals(self): # this code is partly borrowed from pypy.translator.c.funcgen.FunctionCodeGenerator # TODO: refactoring to avoid code duplication + # and borrowed again from gencli graph = self.graph mix = [graph.getreturnvar()] @@ -226,7 +207,7 @@ for v in mix: is_var = isinstance(v, flowmodel.Variable) if id(v) not in seen and is_var and v.name not in args and v.concretetype is not Void: - locals.append(self.cts.llvar_to_cts(v)) + locals.append(v.name) seen[id(v)] = True self.locals = locals Modified: pypy/dist/pypy/translator/js2/test/test_snippet.py ============================================================================== --- pypy/dist/pypy/translator/js2/test/test_snippet.py (original) +++ pypy/dist/pypy/translator/js2/test/test_snippet.py Wed May 31 15:43:54 2006 @@ -63,12 +63,12 @@ assert f(1027) == 1027 def test_factorial2(self): - py.test.skip("unknown error") + #py.test.skip("unknown error") factorial2 = compile_function(test.factorial2, [int]) assert factorial2(5) == 120 def test_factorial(self): - py.test.skip("unknown error") + #py.test.skip("unknown error") factorial = compile_function(test.factorial, [int]) assert factorial(5) == 120 From pedronis at codespeak.net Wed May 31 15:48:08 2006 From: pedronis at codespeak.net (pedronis at codespeak.net) Date: Wed, 31 May 2006 15:48:08 +0200 (CEST) Subject: [pypy-svn] r27988 - pypy/extradoc/talk/dls2006 Message-ID: <20060531134808.73BB710060@code0.codespeak.net> Author: pedronis Date: Wed May 31 15:48:07 2006 New Revision: 27988 Modified: pypy/extradoc/talk/dls2006/paper.bib Log: stop bibtex from abbreviating PyPy Team Modified: pypy/extradoc/talk/dls2006/paper.bib ============================================================================== --- pypy/extradoc/talk/dls2006/paper.bib (original) +++ pypy/extradoc/talk/dls2006/paper.bib Wed May 31 15:48:07 2006 @@ -171,14 +171,14 @@ @misc{T, title = {PyPy - Translation}, -author = {PyPy Team}, +author = "{PyPy Team}", url = {http://codespeak.net/pypy/dist/pypy/doc/translation.html}, howpublished = {Web page, in-progress.} } @misc{A, title = {PyPy - Architecture Overview}, -author = {PyPy Team}, +author = "{PyPy Team}", url = {http://codespeak.net/pypy/dist/pypy/doc/architecture.html}, howpuplished = {Web page} } From arigo at codespeak.net Wed May 31 16:07:10 2006 From: arigo at codespeak.net (arigo at codespeak.net) Date: Wed, 31 May 2006 16:07:10 +0200 (CEST) Subject: [pypy-svn] r27992 - pypy/extradoc/talk/dls2006 Message-ID: <20060531140710.2A51810060@code0.codespeak.net> Author: arigo Date: Wed May 31 16:07:09 2006 New Revision: 27992 Modified: pypy/extradoc/talk/dls2006/paper.bib pypy/extradoc/talk/dls2006/paper.tex Log: A reference for partial evaluation. Modified: pypy/extradoc/talk/dls2006/paper.bib ============================================================================== --- pypy/extradoc/talk/dls2006/paper.bib (original) +++ pypy/extradoc/talk/dls2006/paper.bib Wed May 31 16:07:09 2006 @@ -209,3 +209,11 @@ title = "Graphviz - Graph Visualization Software", organization = "AT&T", } + + at Book{Jones:1993:PartialEvaluation, + author = "N.D. Jones and C.K. Gomard and P. Sestoft", + title = "Partial Evaluation and Automatic Program Generation", + publisher = P-H, + year = "1993", + isbn = "0-13-020249-5", + note = ""} Modified: pypy/extradoc/talk/dls2006/paper.tex ============================================================================== --- pypy/extradoc/talk/dls2006/paper.tex (original) +++ pypy/extradoc/talk/dls2006/paper.tex Wed May 31 16:07:09 2006 @@ -1082,10 +1082,11 @@ from the start -- the possibility to produce a JIT as a graph transformation aspect from the Python interpreter. This idea is based on the theoretical possibiliy to turn interpreters into compilers by -partial evaluation [PE]. In our approach, this is done by analysing +partial evaluation\cite{Jones:1993:PartialEvaluation}. +In our approach, this is done by analysing the forest of flow graphs built from the Python interpreter, which is a well-suited input for this kind of techniques. We can currently perform -binding-time analysis [BTA] on these graphs, again with abstract +binding-time analysis on these graphs, again with abstract interpretation techniques reusing the type inference engine. The next step is to transform the graphs -- following the binding-time annotations - into a compiler; more precisely, in partial evalution terminology, a From cfbolz at codespeak.net Wed May 31 16:11:13 2006 From: cfbolz at codespeak.net (cfbolz at codespeak.net) Date: Wed, 31 May 2006 16:11:13 +0200 (CEST) Subject: [pypy-svn] r27993 - pypy/extradoc/talk/dls2006 Message-ID: <20060531141113.7BFCF10063@code0.codespeak.net> Author: cfbolz Date: Wed May 31 16:11:12 2006 New Revision: 27993 Modified: pypy/extradoc/talk/dls2006/paper.tex Log: remove hyperlink and add real reference Modified: pypy/extradoc/talk/dls2006/paper.tex ============================================================================== --- pypy/extradoc/talk/dls2006/paper.tex (original) +++ pypy/extradoc/talk/dls2006/paper.tex Wed May 31 16:11:12 2006 @@ -1,5 +1,4 @@ \documentclass{acm_proc_article-sp} -\usepackage[colorlinks=true,linkcolor=blue,urlcolor=blue]{hyperref} \begin{document} @@ -133,7 +132,6 @@ \section{System programming in Python} \label{systemprog} -\hypertarget{the-translation-process}{} \subsection{The translation process} \label{translationprocess} @@ -442,13 +440,11 @@ \subsection{Building control flow graphs} \label{flowobjspace} -\hypertarget{flowobjspace}{} -As described in the overview of \href{\#the-translation-process}{the -translation process}, the front-end of the translation tool-chain -works in two phases: it first builds control flow graphs from Python -functions, and then performs whole-program type inference on these -graphs. +As described in the overview of the translation process (section +\ref{translationprocess}), the front-end of the translation tool-chain works in +two phases: it first builds control flow graphs from Python functions, and then +performs whole-program type inference on these graphs. Remember that building the control flow graphs is not done, as one might first expect, by following a function at the syntactic level. Instead, @@ -596,7 +592,7 @@ Here is a simplified, static model of how the annotator works. It can be considered as taking as input a finite family of functions calling each other, and working on the control flow graphs of each of these -functions as built by the \href{flowobjspace}{Flow Object Space}. +functions as built by the Flow Object Space (section \ref{flowobjspace}). Additionally, for a particular "entry point" function, the annotator is provided with user-specified types for the function's arguments. From cfbolz at codespeak.net Wed May 31 16:20:20 2006 From: cfbolz at codespeak.net (cfbolz at codespeak.net) Date: Wed, 31 May 2006 16:20:20 +0200 (CEST) Subject: [pypy-svn] r27997 - pypy/extradoc/talk/dls2006 Message-ID: <20060531142020.5B0B510060@code0.codespeak.net> Author: cfbolz Date: Wed May 31 16:20:19 2006 New Revision: 27997 Modified: pypy/extradoc/talk/dls2006/paper.tex Log: add a missing "section" Modified: pypy/extradoc/talk/dls2006/paper.tex ============================================================================== --- pypy/extradoc/talk/dls2006/paper.tex (original) +++ pypy/extradoc/talk/dls2006/paper.tex Wed May 31 16:20:19 2006 @@ -314,7 +314,7 @@ the restriction of having to use pointer-like and address-like objects, Python remains more expressive than, say, C to write a GC (Jikes RVM's GC work \cite{JikesGC} was the inspiration to try to -express GCs in Python, see \ref{relatedwork}). +express GCs in Python, see section \ref{relatedwork}). In the sequel, we will call \textit{system code} functions written in Python that are meant to be analysed by the front-end. For the From pedronis at codespeak.net Wed May 31 16:22:10 2006 From: pedronis at codespeak.net (pedronis at codespeak.net) Date: Wed, 31 May 2006 16:22:10 +0200 (CEST) Subject: [pypy-svn] r27998 - pypy/extradoc/talk/dls2006 Message-ID: <20060531142210.4428910053@code0.codespeak.net> Author: pedronis Date: Wed May 31 16:22:09 2006 New Revision: 27998 Modified: pypy/extradoc/talk/dls2006/paper.bib Log: use notes to get the url in the final text. D05.1 needs a saner url please. Modified: pypy/extradoc/talk/dls2006/paper.bib ============================================================================== --- pypy/extradoc/talk/dls2006/paper.bib (original) +++ pypy/extradoc/talk/dls2006/paper.bib Wed May 31 16:22:09 2006 @@ -140,7 +140,7 @@ % Jikes jit, more recent techreport @techreport{Jikes-JIT, title = {Architecture and Policy for Adaptive Optimization in Virtual Machines}, - author = {Matthew Arnold, Stephen Fink, David Grove, Michael Hind, and Peter F. Sweeney}, + author = {Matthew Arnold and Stephen Fink and David Grove and Michael Hind and Peter F. Sweeney}, year = 2004, institution = {IBM Research}, number = 23429, @@ -166,26 +166,29 @@ author = {Armin Rigo and Michael Hudson and Samuele Pedroni}, year = {2005}, institution = {PyPy Consortium}, -url = {http://codespeak.net/~cfbolz/eu-reports/D05.1_Publish_on_translating_a_very-high-level_description.pdf} +url = {http://codespeak.net/~cfbolz/eu-reports/D05.1_Publish_on_translating_a_very-high-level_description.pdf}, +note = {http://codespeak.net/\~cfbolz/eu-reports/D05.1\_Publish\_on\_translating \_a\_very-high-level\_description.pdf} } @misc{T, title = {PyPy - Translation}, author = "{PyPy Team}", url = {http://codespeak.net/pypy/dist/pypy/doc/translation.html}, +note = {http://codespeak.net/pypy/dist/pypy/doc/translation.html}, howpublished = {Web page, in-progress.} } @misc{A, title = {PyPy - Architecture Overview}, author = "{PyPy Team}", -url = {http://codespeak.net/pypy/dist/pypy/doc/architecture.html}, -howpuplished = {Web page} +note = {http://codespeak.net/pypy/dist/pypy/doc/architecture.html}, +url = "http://codespeak.net/pypy/dist/pypy/doc/architecture.html", +howpublished = {Web page} } % Boehm - at article{52202, + at article{Boehm, author = {Hans-Juergen Boehm and Mark Weiser}, title = {Garbage collection in an uncooperative environment}, journal = {Softw. Pract. Exper.}, From pedronis at codespeak.net Wed May 31 16:35:19 2006 From: pedronis at codespeak.net (pedronis at codespeak.net) Date: Wed, 31 May 2006 16:35:19 +0200 (CEST) Subject: [pypy-svn] r28001 - pypy/extradoc/talk/dls2006 Message-ID: <20060531143519.99D6710053@code0.codespeak.net> Author: pedronis Date: Wed May 31 16:35:17 2006 New Revision: 28001 Modified: pypy/extradoc/talk/dls2006/paper.bib pypy/extradoc/talk/dls2006/paper.tex Log: more bib tweaks Modified: pypy/extradoc/talk/dls2006/paper.bib ============================================================================== --- pypy/extradoc/talk/dls2006/paper.bib (original) +++ pypy/extradoc/talk/dls2006/paper.bib Wed May 31 16:35:17 2006 @@ -98,8 +98,6 @@ year = {2004}, pages = {137-146}, ee = {http://csdl.computer.org/comp/proceedings/icse/2004/2163/00/21630137abs.htm}, - crossref = {DBLP:conf/icse/2004}, - bibsource = {DBLP, http://dblp.uni-trier.de} } % old overview paper @@ -204,19 +202,21 @@ @misc{boehm-softw, author = "Hans Boehm", title = "A garbage collector for C and C++", -url = "http://www.hpl.hp.com/personal/Hans_Boehm/gc/" +url = "http://www.hpl.hp.com/personal/Hans_Boehm/gc/", +note = "http://www.hpl.hp.com/personal/Hans\_Boehm/gc/" } @misc{graphviz, -url = "http://www.graphviz.org/", title = "Graphviz - Graph Visualization Software", -organization = "AT&T", +author = "{AT\&T}", +note = "http://www.graphviz.org/", +url = "http://www.graphviz.org/" } @Book{Jones:1993:PartialEvaluation, author = "N.D. Jones and C.K. Gomard and P. Sestoft", title = "Partial Evaluation and Automatic Program Generation", - publisher = P-H, + publisher = "P-H", year = "1993", isbn = "0-13-020249-5", note = ""} Modified: pypy/extradoc/talk/dls2006/paper.tex ============================================================================== --- pypy/extradoc/talk/dls2006/paper.tex (original) +++ pypy/extradoc/talk/dls2006/paper.tex Wed May 31 16:35:17 2006 @@ -205,8 +205,8 @@ transformation step produces flow graphs that also assume automatic memory management. Generating C code directly from there produces a fully leaking program, unless we link it with an external garbage -collector (GC) like the Boehm conservative GC \cite{Boehm}, which is a -viable option. +collector (GC) like the Boehm conservative GC \cite{Boehm}\cite{boehm-softw}, +which is a viable option. We have two alternatives, each implemented as a transformation step. The first one inserts naive reference counting throughout the whole @@ -464,7 +464,7 @@ of any intermediate step to disk. Figure 3 shows the control flow graph obtained for a simple function -- this is a screenshot from our graph viewer, used for debugging; basic block placement is performed by -[Graphviz]. +Graphviz \cite{graphviz}. \begin{verbatim} :: From pedronis at codespeak.net Wed May 31 16:38:57 2006 From: pedronis at codespeak.net (pedronis at codespeak.net) Date: Wed, 31 May 2006 16:38:57 +0200 (CEST) Subject: [pypy-svn] r28003 - pypy/extradoc/talk/dls2006 Message-ID: <20060531143857.B78F410060@code0.codespeak.net> Author: pedronis Date: Wed May 31 16:38:56 2006 New Revision: 28003 Modified: pypy/extradoc/talk/dls2006/paper.tex Log: references for Boehm already introduced before. Modified: pypy/extradoc/talk/dls2006/paper.tex ============================================================================== --- pypy/extradoc/talk/dls2006/paper.tex (original) +++ pypy/extradoc/talk/dls2006/paper.tex Wed May 31 16:38:56 2006 @@ -944,7 +944,7 @@ {\bf pypy-c.} The simplest variant: translated to C code with no explicit memory - management, and linked with the Boehm conservative GC [Boehm]. + management, and linked with the Boehm conservative GC. {\bf pypy-c-thread.} The same, with OS thread support enabled. (For measurement purposes, From pedronis at codespeak.net Wed May 31 16:54:21 2006 From: pedronis at codespeak.net (pedronis at codespeak.net) Date: Wed, 31 May 2006 16:54:21 +0200 (CEST) Subject: [pypy-svn] r28005 - pypy/extradoc/talk/dls2006 Message-ID: <20060531145421.7012910053@code0.codespeak.net> Author: pedronis Date: Wed May 31 16:54:20 2006 New Revision: 28005 Modified: pypy/extradoc/talk/dls2006/paper.bib pypy/extradoc/talk/dls2006/paper.tex Log: some more reference and tweaks Modified: pypy/extradoc/talk/dls2006/paper.bib ============================================================================== --- pypy/extradoc/talk/dls2006/paper.bib (original) +++ pypy/extradoc/talk/dls2006/paper.bib Wed May 31 16:54:20 2006 @@ -10,7 +10,7 @@ } % Hindley-Milner - at inproceedings{582176, + at inproceedings{DaMi, author = {Luis Damas and Robin Milner}, title = {Principal type-schemes for functional programs}, booktitle = {POPL '82: Proceedings of the 9th ACM SIGPLAN-SIGACT symposium on Principles of programming languages}, @@ -23,7 +23,7 @@ address = {New York, NY, USA}, } - at article{DBLP:journals/jcss/Milner78, + at article{Miln, author = {Robin Milner}, title = {A Theory of Type Polymorphism in Programming.}, journal = {J. Comput. Syst. Sci.}, @@ -68,13 +68,13 @@ address = {New York, NY, USA}, } - at misc{ kelsey-prescheme, + at misc{kelsey-prescheme, author = "R. Kelsey", title = "Pre-Scheme: A Scheme Dialect for Systems Programming", text = "Richard Kelsey. Pre-Scheme: A Scheme Dialect for Systems Programming. ?." } % Psyco - at inproceedings{1014010, + at inproceedings{psyco, author = {Armin Rigo}, title = {Representation-based just-in-time specialization and the psyco prototype for python}, booktitle = {PEPM '04: Proceedings of the 2004 ACM SIGPLAN symposium on Partial evaluation and semantics-based program manipulation}, @@ -101,7 +101,7 @@ } % old overview paper - at article{DBLP:journals/ibmsj/AlpernABBCCCFGHHLLMNRSSSSSSW00, + at article{jalapeno, author = {Bowen Alpern and C. Richard Attanasio and John J. Barton and @@ -220,3 +220,17 @@ year = "1993", isbn = "0-13-020249-5", note = ""} + + at article{Dhry20, + author = {R. P. Weicker}, + title = {Dhrystone benchmark: rationale for version 2 and measurement rules}, + journal = {SIGPLAN Not.}, + volume = {23}, + number = {8}, + year = {1988}, + issn = {0362-1340}, + pages = {49--62}, + doi = {http://doi.acm.org/10.1145/47907.47911}, + publisher = {ACM Press}, + address = {New York, NY, USA}, + } \ No newline at end of file Modified: pypy/extradoc/talk/dls2006/paper.tex ============================================================================== --- pypy/extradoc/talk/dls2006/paper.tex (original) +++ pypy/extradoc/talk/dls2006/paper.tex Wed May 31 16:54:20 2006 @@ -608,18 +608,19 @@ Python -- like many languages not specifically designed with type inference in mind -- does not possess a type system that allows much useful information to be derived about variables based on how they are -\textit{used}; only on how they were \textit{produced}. For example, a number of very -different built-in types can be involved in an addition; the meaning of -the addition and the type of the result depends on the type of the input -arguments. Merely knowing that a variable will be used in an addition -does not give much information per se. For this reason, our annotator -works by flowing types forward, operation after operation, i.e.\ by -performing abstract interpretation of the flow graphs. In a sense, it -is a more naive approach than the one taken by type systems specifically -designed to enable more advanced inference algorithms. For example, +\textit{used}; only on how they were \textit{produced}. For example, +a number of very different built-in types can be involved in an +addition; the meaning of the addition and the type of the result +depends on the type of the input arguments. Merely knowing that a +variable will be used in an addition does not give much information +per se. For this reason, our annotator works by flowing types +forward, operation after operation, i.e.\ by performing abstract +interpretation of the flow graphs. In a sense, it is a more naive +approach than the one taken by type systems specifically designed to +enable more advanced inference algorithms. For example, Hindley-Milner type inference works in an inside-out direction, by starting from individual operations and propagating type constraints -outwards [H-M]. +outwards \cite{DaMi}\cite{Miln}. Naturally, simply propagating types forward requires the use of a fixed point algorithm in the presence of loops in the flow graphs or in the @@ -909,8 +910,8 @@ The tool-chain has been tested with and can sucessfully apply transformations enabling various combinations of features. The -translated interpreters are benchmarked using pystone (a [Dhrystone] 2.0 -derivative traditionally used by the Python community, although it is +translated interpreters are benchmarked using pystone (a Dhrystone 2.0 +\cite{dhry20} derivative traditionally used by the Python community, although it is a rather poor benchmark) and the classical [Richards] benchmark and compared against [CPython] 2.4.3 results and are summarized in table \ref{perfsumm}. @@ -1089,8 +1090,8 @@ generating extension. We can currently do this on trivial examples. The resulting generating extension will be essentially similar to -[Psyco], which is the only (and hand-written) JIT available for Python so -far, based on run-time specialization. +Psyco \cite{psyco}, which is the only (and hand-written) JIT available for Python +so far, based on run-time specialization. @@ -1127,7 +1128,7 @@ portability were the major goals, as opposed to sophisticated manipulation and analysis or "weaving" in of features as transformation aspects. -Jikes RVM \cite{DBLP:journals/ibmsj/AlpernABBCCCFGHHLLMNRSSSSSSW00} is a +Jikes RVM \cite{jalapeno} is a Java VM and Just-In-Time compiler written in Java. Bootstrapping happens by self-applying the compiler on a host VM, and dumping a snapshot from memory of the resulting native code. From arigo at codespeak.net Wed May 31 16:59:40 2006 From: arigo at codespeak.net (arigo at codespeak.net) Date: Wed, 31 May 2006 16:59:40 +0200 (CEST) Subject: [pypy-svn] r28006 - pypy/dist/pypy/doc Message-ID: <20060531145940.4029810053@code0.codespeak.net> Author: arigo Date: Wed May 31 16:59:38 2006 New Revision: 28006 Modified: pypy/dist/pypy/doc/index-report.txt Log: Link to the reports now in extradoc. Modified: pypy/dist/pypy/doc/index-report.txt ============================================================================== --- pypy/dist/pypy/doc/index-report.txt (original) +++ pypy/dist/pypy/doc/index-report.txt Wed May 31 16:59:38 2006 @@ -36,13 +36,12 @@ project during the first year of EU funding (December 2004 - December 2005) -.. _`D04.1 Partial Python Implementation`: http://codespeak.net/~cfbolz/eu-reports/D04.1_Partial_Python_Implementation_on_top_of_CPython.pdf -.. _`D04.2 Complete Python Implementation`: http://codespeak.net/~cfbolz/eu-reports/D04.2_Complete_Python_Implementation_on_top_of_CPython.pdf -.. _`D04.3 Parser and Bytecode Compiler`: http://codespeak.net/~cfbolz/eu-reports/D04.3_Report_about_the_parser_and_bytecode_compiler.pdf -.. _`D04.4 PyPy as a Research Tool`: http://codespeak.net/~cfbolz/eu-reports/D04.4_Release_PyPy_as_a_research_tool.pdf -.. _`D05.1 Compiling Dynamic Language Implementations`: http://codespeak.net/~cfbolz/eu-reports/D05.1_Publish_on_translating_a_very-high-level_description.pdf -.. _`D05.2 A Compiled Version of PyPy`: http://codespeak.net/~cfbolz/eu-reports/D05.2_A_compiled,_self-contained_version_of_PyPy.pdf -.. _`D05.3 Implementation with Translation Aspects`: http://codespeak.net/~cfbolz/eu-reports/D05.3_Publish_on_implementation_with_translation_aspects.pdf -.. _`D05.4 Encapsulating Low Level Aspects`: http://codespeak.net/~cfbolz/eu-reports/D05.4_Publish_on_encapsulating_low_level_language_aspects.pdf -.. _`D14.1 Report about Milestone/Phase 1`: http://codespeak.net/~cfbolz/eu-reports/D14.1_Report_about_Milestone_Phase_1.pdf - +.. _`D04.1 Partial Python Implementation`: http://codespeak.net/svn/pypy/extradoc/eu-report/D04.1_Partial_Python_Implementation_on_top_of_CPython.pdf +.. _`D04.2 Complete Python Implementation`: http://codespeak.net/svn/pypy/extradoc/eu-report/D04.2_Complete_Python_Implementation_on_top_of_CPython.pdf +.. _`D04.3 Parser and Bytecode Compiler`: http://codespeak.net/svn/pypy/extradoc/eu-report/D04.3_Report_about_the_parser_and_bytecode_compiler.pdf +.. _`D04.4 PyPy as a Research Tool`: http://codespeak.net/svn/pypy/extradoc/eu-report/D04.4_Release_PyPy_as_a_research_tool.pdf +.. _`D05.1 Compiling Dynamic Language Implementations`: http://codespeak.net/svn/pypy/extradoc/eu-report/D05.1_Publish_on_translating_a_very-high-level_description.pdf +.. _`D05.2 A Compiled Version of PyPy`: http://codespeak.net/svn/pypy/extradoc/eu-report/D05.2_A_compiled,_self-contained_version_of_PyPy.pdf +.. _`D05.3 Implementation with Translation Aspects`: http://codespeak.net/svn/pypy/extradoc/eu-report/D05.3_Publish_on_implementation_with_translation_aspects.pdf +.. _`D05.4 Encapsulating Low Level Aspects`: http://codespeak.net/svn/pypy/extradoc/eu-report/D05.4_Publish_on_encapsulating_low_level_language_aspects.pdf +.. _`D14.1 Report about Milestone/Phase 1`: http://codespeak.net/svn/pypy/extradoc/eu-report/D14.1_Report_about_Milestone_Phase_1.pdf From pedronis at codespeak.net Wed May 31 17:05:22 2006 From: pedronis at codespeak.net (pedronis at codespeak.net) Date: Wed, 31 May 2006 17:05:22 +0200 (CEST) Subject: [pypy-svn] r28007 - pypy/extradoc/talk/dls2006 Message-ID: <20060531150522.3ABB31005A@code0.codespeak.net> Author: pedronis Date: Wed May 31 17:05:21 2006 New Revision: 28007 Modified: pypy/extradoc/talk/dls2006/paper.tex Log: [D|T] -> \cite Modified: pypy/extradoc/talk/dls2006/paper.tex ============================================================================== --- pypy/extradoc/talk/dls2006/paper.tex (original) +++ pypy/extradoc/talk/dls2006/paper.tex Wed May 31 17:05:21 2006 @@ -707,7 +707,7 @@ out a number of other annotations that are irrelevant for the basic description of the annotator and straightforward to handle: $Dictionary$, $Tuple$, $Float$, $UnicodePoint$, $Iterator$, etc. The -complete list is described in [T]. +complete list is described in document \cite{T}. The type system moreover comes with a family of rules, which for every operation and every sensible combination of input types describes the @@ -751,14 +751,15 @@ It is outside the scope of the present paper to describe the type inference engine and the rules more formally. The difficult points -involve mutable containers -- e.g.\ initially empty list that are filled -somewhere else -- and the discovery of instance attributes -- in Python, -classes do not declare upfront a fixed set of attributes for their -instances, let alone their types. Both these examples require -sophisticated reflowing techniques that invalidate existing types in -already-annotated basic blocks, to account for the influence of more -general types coming indirectly from a possibly distant part of the -program. The reader is referred to [D] for more information. +involve mutable containers -- e.g.\ initially empty list that are +filled somewhere else -- and the discovery of instance attributes -- +in Python, classes do not declare upfront a fixed set of attributes +for their instances, let alone their types. Both these examples +require sophisticated reflowing techniques that invalidate existing +types in already-annotated basic blocks, to account for the influence +of more general types coming indirectly from a possibly distant part +of the program. The reader is referred to technical report \cite{D} +for more information. \subsection{Termination and complexity} @@ -792,7 +793,7 @@ order of 5 to 10 minutes, and basic blocks are typically only reflown a handful of times, providing a close-to-linear practical complexity. -We give formal termination and correctness proofs in [D], as well as +We give formal termination and correctness proofs in \cite{D}, as well as worst-case bounds and some experimental evidence of their practical irrelevance. From arigo at codespeak.net Wed May 31 17:08:56 2006 From: arigo at codespeak.net (arigo at codespeak.net) Date: Wed, 31 May 2006 17:08:56 +0200 (CEST) Subject: [pypy-svn] r28008 - pypy/extradoc/talk/dls2006 Message-ID: <20060531150856.E5A3710060@code0.codespeak.net> Author: arigo Date: Wed May 31 17:08:55 2006 New Revision: 28008 Modified: pypy/extradoc/talk/dls2006/paper.bib pypy/extradoc/talk/dls2006/paper.tex Log: More URL fighting. Modified: pypy/extradoc/talk/dls2006/paper.bib ============================================================================== --- pypy/extradoc/talk/dls2006/paper.bib (original) +++ pypy/extradoc/talk/dls2006/paper.bib Wed May 31 17:08:55 2006 @@ -164,8 +164,17 @@ author = {Armin Rigo and Michael Hudson and Samuele Pedroni}, year = {2005}, institution = {PyPy Consortium}, -url = {http://codespeak.net/~cfbolz/eu-reports/D05.1_Publish_on_translating_a_very-high-level_description.pdf}, -note = {http://codespeak.net/\~cfbolz/eu-reports/D05.1\_Publish\_on\_translating \_a\_very-high-level\_description.pdf} +url = {http://codespeak.net/svn/pypy/extradoc/eu-report/D05.1_Publish_on_translating_a_very-high-level_description.pdf}, +note = {http://codespeak.net/svn/pypy/extradoc/eu-report/} +} + + at techreport{S, +title = {Complete Python Implementation running on top of CPython}, +author = "{PyPy Team}", +year = {2005}, +institution = {PyPy Consortium}, +url = {http://codespeak.net/svn/pypy/extradoc/eu-report/D04.2_Complete_Python_Implementation_on_top_of_CPython.pdf}, +note = {http://codespeak.net/svn/pypy/extradoc/eu-report/} } @misc{T, Modified: pypy/extradoc/talk/dls2006/paper.tex ============================================================================== --- pypy/extradoc/talk/dls2006/paper.tex (original) +++ pypy/extradoc/talk/dls2006/paper.tex Wed May 31 17:08:55 2006 @@ -493,7 +493,7 @@ an RPython program, and the whole purpose of the translation process is to accept this as \textit{input}, and translate it to an efficient form. The description of this particular input program is beyond the scope of -the present paper; see [S]. +the present paper; see \cite{S}. However, the bytecode interpreter plays a double role, at two different levels. The so-called Object Spaces are \textit{domains} in the abstract From pedronis at codespeak.net Wed May 31 17:14:12 2006 From: pedronis at codespeak.net (pedronis at codespeak.net) Date: Wed, 31 May 2006 17:14:12 +0200 (CEST) Subject: [pypy-svn] r28009 - pypy/extradoc/talk/dls2006 Message-ID: <20060531151412.E4EB11005A@code0.codespeak.net> Author: pedronis Date: Wed May 31 17:14:11 2006 New Revision: 28009 Modified: pypy/extradoc/talk/dls2006/paper.tex Log: title Modified: pypy/extradoc/talk/dls2006/paper.tex ============================================================================== --- pypy/extradoc/talk/dls2006/paper.tex (original) +++ pypy/extradoc/talk/dls2006/paper.tex Wed May 31 17:14:11 2006 @@ -2,9 +2,7 @@ \begin{document} -\title{Still Missing a Cool Title} - -% title ideas: Implementing Virtual Machines in Dynamic Languages? +\title{PyPy's Approach to Virtual Machine Construction} \numberofauthors{2} \author{ From mwh at codespeak.net Wed May 31 17:23:00 2006 From: mwh at codespeak.net (mwh at codespeak.net) Date: Wed, 31 May 2006 17:23:00 +0200 (CEST) Subject: [pypy-svn] r28010 - pypy/extradoc/talk/dls2006 Message-ID: <20060531152300.851B61005A@code0.codespeak.net> Author: mwh Date: Wed May 31 17:22:58 2006 New Revision: 28010 Modified: pypy/extradoc/talk/dls2006/paper.tex Log: sort out quote marks (I love query-replace-regexp) Modified: pypy/extradoc/talk/dls2006/paper.tex ============================================================================== --- pypy/extradoc/talk/dls2006/paper.tex (original) +++ pypy/extradoc/talk/dls2006/paper.tex Wed May 31 17:22:58 2006 @@ -61,11 +61,11 @@ and for CLI/.NET. This is, at least, the current situation of the Python programming language, where independent volunteers have developed and are now maintaining Java and .NET versions of Python, -which follow the evolution of the "official" C version (CPython). +which follow the evolution of the ``official'' C version (CPython). However, we believe that platform standardization does not have to be a necessary component of this equation. We are basically using the -standard "meta-programming" argument: if one could write the VM in a +standard ``meta-programming'' argument: if one could write the VM in a very high level language, then the VM itself could be automatically \textit{translated} to any lower-level platform. Moreover by writing the VM in such a language we would gain in flexibility in @@ -112,7 +112,7 @@ \end{enumerate} % In particular, we have defined a subset of the Python language called -"restricted Python" or RPython. This sublanguage is not restricted +``restricted Python'' or RPython. This sublanguage is not restricted syntactically, but only in the way it manipulates objects of different types. The restrictions are a compromise between the expressivity and the need to statically infer enough types to generate efficient code. @@ -267,7 +267,7 @@ This means that in addition to transforming the existing graphs, each transformation step also needs to insert new functions into the forest. -A key feature of our approach is that we can write such "system-level" +A key feature of our approach is that we can write such ``system-level'' code -- relevant only to a particular transformation -- in plain Python as well. The idea is to feed these new Python functions into the front-end, using this time the transformation's target (lower-level) @@ -307,7 +307,7 @@ In the example of the \texttt{malloc} operation, replaced by a call to GC code, this GC code can invoke a complete collection of dead objects, and can thus be arbitrarily complicated. Still, our GC code -is entirely written in plain Python, and it manipulates "objects" that +is entirely written in plain Python, and it manipulates ``objects'' that are still at a lower level: pointer and address objects. Even with the restriction of having to use pointer-like and address-like objects, Python remains more expressive than, say, C to write a GC @@ -380,8 +380,8 @@ can also be used by type inference when analysing system code like the helpers of figure \ref{fig_llappend}. -Now, clearly, the purpose of types like a "C-like struct" or a "C-like -array" is to be translated to a real \texttt{struct} or array declaration by +Now, clearly, the purpose of types like a ``C-like struct'' or a ``C-like +array'' is to be translated to a real \texttt{struct} or array declaration by the C back-end. What, then, is the purpose of emulating such things in Python? The answer is three-fold. Firstly, if we have objects that live within the Python interpreter, but faithfully emulate the behavior @@ -535,7 +535,7 @@ translate. The Flow Object Space records all operations that the bytecode -interpreter "would like" to do between the placeholder objects. It +interpreter ``would like'' to do between the placeholder objects. It records them into basic block objects that will eventually be part of the control flow graph of the whole function. The recorded operations take Variables and Constants as argument, and produce new Variables as @@ -591,7 +591,7 @@ be considered as taking as input a finite family of functions calling each other, and working on the control flow graphs of each of these functions as built by the Flow Object Space (section \ref{flowobjspace}). -Additionally, for a particular "entry point" function, the annotator +Additionally, for a particular ``entry point'' function, the annotator is provided with user-specified types for the function's arguments. The goal of the annotator is to find the most precise type that can be @@ -634,7 +634,7 @@ types that flow into the following blocks, and so on. This process continues until a fixed point is reached. -We can consider that all variables are initially assigned the "bottom" +We can consider that all variables are initially assigned the ``bottom'' type corresponding to the empty set of possible run-time values. Types can only ever be generalised, and the model is simple enough to show that there is no infinite chain of generalisation, so that this process @@ -654,7 +654,7 @@ % \begin{itemize} \item $Bot$, $Top$ -- the minimum and maximum elements (corresponding - to "impossible value" and "most general value"); + to ``impossible value'' and ``most general value''); \item $Int$, $NonNegInt$, $Bool$ -- integers, known-non-negative integers, booleans; @@ -711,7 +711,7 @@ operation and every sensible combination of input types describes the type of its result variable. Let $V$ be the set of Variables that appear in the user program's flow graphs. Let $b$ be a map from $V$ -to $A$; it is a "binding" that gives to each variable a type. The +to $A$; it is a ``binding'' that gives to each variable a type. The purpose of the annotator is to compute such a binding stepwise. Let $x$, $y$ and $z$ be Variables. We introduce the rules: @@ -952,12 +952,12 @@ performance.) {\bf pypy-c-stackless.} - The same as pypy-c, plus the "stackless transformation" step which + The same as pypy-c, plus the ``stackless transformation'' step which modifies the flow graph of all functions in a way that allows them to save and restore their local state, as a way to enable coroutines. {\bf pypy-c-gcframework.} - In this variant, the "gc transformation" step inserts explicit + In this variant, the ``gc transformation'' step inserts explicit memory management and a simple mark-and-sweep GC implementation. The resulting program is not linked with Boehm. Note that it is not possible to find all roots from the C stack in portable C; instead, @@ -965,8 +965,8 @@ to an alternate stack around each subcall. {\bf pypy-c-stackless-gcframework.} - This variant combines the "gc transformation" step with the - "stackless transformation" step. The overhead introduced by the + This variant combines the ``gc transformation'' step with the + ``stackless transformation'' step. The overhead introduced by the stackless feature is theoretically balanced with the removal of the overhead of pushing and popping roots explicitly on an alternate stack: indeed, in this variant it is possible to ask the functions @@ -1041,7 +1041,7 @@ although it has a linear complexity on the size of its input (most transformations do). -Other transformations like the "gc" and the "stackless" ones actually +Other transformations like the ``gc'' and the ``stackless'' ones actually take more time, particuarly when used in combination with each other (we speculate it is because of the increase in size caused by the previous transformations). A translation of pypy-c-stackless, without counting @@ -1066,7 +1066,7 @@ So far, the PyPy tool-chain can only translate the Python interpreter of PyPy into a program which is again an interpreter -- the same interpreter translated to C, essentially, although we have already shown that some -aspects can be "weaved" in at translation time, like support for +aspects can be ``weaved'' in at translation time, like support for coroutines. To achieve high performance for dynamic languages such as Python, the @@ -1125,7 +1125,7 @@ The VM, the object memory and the garbage collector support are explicitly written together in this style. Again simplicity and portability were the major goals, as opposed to sophisticated manipulation -and analysis or "weaving" in of features as transformation aspects. +and analysis or ``weaving'' in of features as transformation aspects. Jikes RVM \cite{jalapeno} is a Java VM and Just-In-Time compiler written in Java. From arigo at codespeak.net Wed May 31 17:39:57 2006 From: arigo at codespeak.net (arigo at codespeak.net) Date: Wed, 31 May 2006 17:39:57 +0200 (CEST) Subject: [pypy-svn] r28013 - pypy/extradoc/talk/dls2006 Message-ID: <20060531153957.7DF8410036@code0.codespeak.net> Author: arigo Date: Wed May 31 17:39:56 2006 New Revision: 28013 Modified: pypy/extradoc/talk/dls2006/paper.tex Log: Rephrase. Modified: pypy/extradoc/talk/dls2006/paper.tex ============================================================================== --- pypy/extradoc/talk/dls2006/paper.tex (original) +++ pypy/extradoc/talk/dls2006/paper.tex Wed May 31 17:39:56 2006 @@ -157,9 +157,9 @@ \begin{enumerate} \item We take as input RPython functions,\footnote{The input to our translation chain are indeed loaded runtime function objects, - not source code or ASTs. This allows us to use unrestricted - python for meta-programming purposes at load time, in a - seemingly staged programming approach, in which the whole of + not source code or ASTs. This enables a form of staged + programming in which we can use unrestricted + Python for meta-programming purposes at load time: the whole of the source program -- as Python program -- produces the RPython program input to the tool-chain as the object graph loaded in memory. This includes both the relevant functions and prebuilt From arigo at codespeak.net Wed May 31 17:41:43 2006 From: arigo at codespeak.net (arigo at codespeak.net) Date: Wed, 31 May 2006 17:41:43 +0200 (CEST) Subject: [pypy-svn] r28014 - pypy/extradoc/talk/dls2006 Message-ID: <20060531154143.C890710060@code0.codespeak.net> Author: arigo Date: Wed May 31 17:41:42 2006 New Revision: 28014 Modified: pypy/extradoc/talk/dls2006/paper.tex Log: LL = low-level Modified: pypy/extradoc/talk/dls2006/paper.tex ============================================================================== --- pypy/extradoc/talk/dls2006/paper.tex (original) +++ pypy/extradoc/talk/dls2006/paper.tex Wed May 31 17:41:42 2006 @@ -238,7 +238,8 @@ type system is designed for \textit{statically-typed} OO environments, including Java; the presence of Smalltalk as a back-end might be misleading in that respect.} and CLI/.NET. This first transformation -step, for C-like environments, is called the \textit{LLTyper}: it produces +step, for C-like environments, is called the \textit{LLTyper} or +low-level typer: it produces C-level flow graphs, where the object-oriented features of RPython (classes and instances) become manipulations of C structs with explicit virtual table pointers. By contrast, for OO environments the From pedronis at codespeak.net Wed May 31 17:49:26 2006 From: pedronis at codespeak.net (pedronis at codespeak.net) Date: Wed, 31 May 2006 17:49:26 +0200 (CEST) Subject: [pypy-svn] r28015 - pypy/extradoc/talk/dls2006 Message-ID: <20060531154926.5361C1005A@code0.codespeak.net> Author: pedronis Date: Wed May 31 17:49:25 2006 New Revision: 28015 Modified: pypy/extradoc/talk/dls2006/paper.bib pypy/extradoc/talk/dls2006/paper.tex Log: cpython 2.4.3 ref no ref for Richards at the moment Modified: pypy/extradoc/talk/dls2006/paper.bib ============================================================================== --- pypy/extradoc/talk/dls2006/paper.bib (original) +++ pypy/extradoc/talk/dls2006/paper.bib Wed May 31 17:49:25 2006 @@ -242,4 +242,13 @@ doi = {http://doi.acm.org/10.1145/47907.47911}, publisher = {ACM Press}, address = {New York, NY, USA}, - } \ No newline at end of file + } + + at misc{cpy243, + author = "Guido van Rossum et al.", + title="{CPython} 1.4.3", + note = "http://www.python.org/download/releases/2.4.3/", + url = "http://www.python.org/download/releases/2.4.3/", + year = 2006, + month = "March", +} Modified: pypy/extradoc/talk/dls2006/paper.tex ============================================================================== --- pypy/extradoc/talk/dls2006/paper.tex (original) +++ pypy/extradoc/talk/dls2006/paper.tex Wed May 31 17:49:25 2006 @@ -911,10 +911,10 @@ The tool-chain has been tested with and can sucessfully apply transformations enabling various combinations of features. The translated interpreters are benchmarked using pystone (a Dhrystone 2.0 -\cite{dhry20} derivative traditionally used by the Python community, although it is -a rather poor benchmark) and the classical [Richards] benchmark and -compared against [CPython] 2.4.3 results and are summarized in table -\ref{perfsumm}. +\cite{dhry20} derivative traditionally used by the Python community, +although it is a rather poor benchmark) and the classical Richards +benchmark (ported to Python) and compared against CPython 2.4.3 \cite{cpy243} +results and are summarized in table \ref{perfsumm}. \begin{table*} % the layout of this table isn't wonderful, but it's probably OK. From arigo at codespeak.net Wed May 31 18:01:27 2006 From: arigo at codespeak.net (arigo at codespeak.net) Date: Wed, 31 May 2006 18:01:27 +0200 (CEST) Subject: [pypy-svn] r28017 - pypy/extradoc/talk/dls2006 Message-ID: <20060531160127.D9D9310060@code0.codespeak.net> Author: arigo Date: Wed May 31 18:01:26 2006 New Revision: 28017 Modified: pypy/extradoc/talk/dls2006/paper.tex Log: Clarify this paragraph (thanks mwh) Modified: pypy/extradoc/talk/dls2006/paper.tex ============================================================================== --- pypy/extradoc/talk/dls2006/paper.tex (original) +++ pypy/extradoc/talk/dls2006/paper.tex Wed May 31 18:01:26 2006 @@ -375,11 +375,13 @@ about them below.) \end{enumerate} % -We have defined well-typed operations between variables of these types, -plugging on the standard Python operators. These operations are the -ones that the emulating instances implement. As seen above, the types -can also be used by type inference when analysing system code like the -helpers of figure \ref{fig_llappend}. +We have defined well-typed operations between instances of these types, +syntactically expressed with standard Python operators (e.g.\ if \texttt{x} +is a C-level array, \texttt{x[n]} accesses its \texttt{n}th item). +The emulating instances provide a concrete implementation of +these operations that works in normal Python; the types involved in the +operations are also known to the type inference engine when it +analyses system code like the helpers of figure \ref{fig_llappend}. Now, clearly, the purpose of types like a ``C-like struct'' or a ``C-like array'' is to be translated to a real \texttt{struct} or array declaration by From mwh at codespeak.net Wed May 31 18:47:30 2006 From: mwh at codespeak.net (mwh at codespeak.net) Date: Wed, 31 May 2006 18:47:30 +0200 (CEST) Subject: [pypy-svn] r28020 - pypy/extradoc/talk/dls2006 Message-ID: <20060531164730.ED4B71005A@code0.codespeak.net> Author: mwh Date: Wed May 31 18:47:29 2006 New Revision: 28020 Modified: pypy/extradoc/talk/dls2006/paper.bib pypy/extradoc/talk/dls2006/paper.tex Log: typos, wording tweaks, small fixes. i'm done, i think. Modified: pypy/extradoc/talk/dls2006/paper.bib ============================================================================== --- pypy/extradoc/talk/dls2006/paper.bib (original) +++ pypy/extradoc/talk/dls2006/paper.bib Wed May 31 18:47:29 2006 @@ -125,7 +125,7 @@ Vugranam C. Sreedhar and Harini Srinivasan and John Whaley}, - title = {The Jalapeo virtual machine.}, + title = {The Jalapeno virtual machine.}, journal = {IBM Systems Journal}, volume = {39}, number = {1}, Modified: pypy/extradoc/talk/dls2006/paper.tex ============================================================================== --- pypy/extradoc/talk/dls2006/paper.tex (original) +++ pypy/extradoc/talk/dls2006/paper.tex Wed May 31 18:47:29 2006 @@ -93,7 +93,7 @@ approach of varying the type systems at various levels of the translation. Section \ref{typeinference} gives an overview of the type inference engine we developed (and can be read independently from -section 3.) We present experimental results in section +section 3). We present experimental results in section \ref{experimentalresults} and future work directions in section \ref{futurework}. In section \ref{relatedwork} we compare with related work, and finally we conclude in section \ref{conclusion}. @@ -108,20 +108,20 @@ language, mostly complete and compliant with the current version of the language, Python 2.4. \item the \textit{Translation Process}: a translation tool-suite whose goal is to -compile subsets of Python to various environment. +compile subsets of Python to various environments. \end{enumerate} % In particular, we have defined a subset of the Python language called ``restricted Python'' or RPython. This sublanguage is not restricted syntactically, but only in the way it manipulates objects of different types. The restrictions are a compromise between the expressivity and -the need to statically infer enough types to generate efficient code. +the need to statically infer enough type information to generate efficient code. The foremost purpose of the translation tool-suite is to compile such RPython programs to a variety of different platforms. Our current efforts, and the present paper, focus on this tool-suite. We will not describe the Standard Interpreter component of PyPy in the -sequel, other than mention that it is written in RPython and can thus be +sequel, other than to mention that it is written in RPython and can thus be translated. At close to 90,000 lines of code, it is the largest RPython program that we have translated so far. More information can be found in \cite{A}. @@ -216,7 +216,7 @@ The other, and better, alternative is an exact GC, coupled with a transformation, the \textit{GC transformer}. It inputs C-level-typed graphs and replaces all \texttt{malloc} operations with calls to a garbage -collector's innards. It can inspect all the graphs to discover the +collector's allocation routine. It can inspect all the graphs to discover the \texttt{struct} types in use by the program, and assign a unique type id to each of them. These type ids are collected in internal tables that describe the layout of the structures, e.g.\ their sizes and the location @@ -312,7 +312,7 @@ are still at a lower level: pointer and address objects. Even with the restriction of having to use pointer-like and address-like objects, Python remains more expressive than, say, C to write a GC -(Jikes RVM's GC work \cite{JikesGC} was the inspiration to try to +(the work on the Jikes RVM's GC \cite{JikesGC} was the inspiration to try to express GCs in Python, see section \ref{relatedwork}). In the sequel, we will call \textit{system code} functions written in @@ -357,7 +357,7 @@ The RPython level is a subset of Python, so the types mostly follow Python types, and the instances of these types are instances in the -normal Python sense; e.g.\ whereas Python has only got a single type +normal Python sense; for example where Python has only a single type \texttt{list}, RPython has a parametric type \texttt{list(T)} for every RPython type \texttt{T}, but instances of \texttt{list(T)} are just those Python lists whose items are all instances of \texttt{T}. @@ -366,13 +366,13 @@ types. For each of them, we implemented: % \begin{enumerate} -\item the types, which we use to tag the variables of the graphs at - the given level. (Types are actually annotated, self-recursive +\item The types, which we use to tag the variables of the graphs at + the given level (types are actually annotated, self-recursive formal terms, and would have been implemented simply as such if - Python supported them directly.) + Python supported them directly). -\item the Python objects that emulate instances of these types. (More - about them below.) +\item The Python objects that emulate instances of these types (more + about them below). \end{enumerate} % We have defined well-typed operations between instances of these types, @@ -386,15 +386,15 @@ Now, clearly, the purpose of types like a ``C-like struct'' or a ``C-like array'' is to be translated to a real \texttt{struct} or array declaration by the C back-end. What, then, is the purpose of emulating such things in -Python? The answer is three-fold. Firstly, if we have objects that +Python? The answer is three-fold. Firstly, having objects that live within the Python interpreter, but faithfully emulate the behavior -of their C equivalent while performing additional safety checks, they -are an invaluable help for testing and debugging. For example, we can +of their C equivalent while performing additional safety checks, is +an invaluable help for testing and debugging. For example, we can check the correctness of our hash table implementation, written in Python in term of struct- and array-like objects, just by running it. The same holds for the GC. -Secondly, and anecdotically, as the type inference process (section +Secondly, and anecdotally, as the type inference process (section \ref{typeinference}) is based on abstract interpretation, we can use the following trick: the resulting type of most low-level operations is deduced simply by example. Sample C-level objects are @@ -422,7 +422,7 @@ controllability and simplicity. This proved essential in our overall approach: as described in section \ref{systemprog}, we need to perform type inference with many different type systems, the details of which -have evolved along the road. +have evolved over time. We mitigate the potential efficiency problem by wise choices and compromises for the domain used; the foremost example of this is that @@ -519,7 +519,7 @@ This order is extremely simple, because most actual analysis is delayed to the next phase, the type inference engine. The objects are either -\textit{Variables}, which are pure placeholders for entierely unknown values, +\textit{Variables}, which are pure placeholders for entirely unknown values, or \textit{Constants} with a concrete Python object as value. The order places Variable as the top, and keeps all \textit{Constants} unordered. Thus if two different constants merge during abstract interpretation, we immediately @@ -566,15 +566,15 @@ operations form a graph, which is the control flow graph of the original bytecode. -Note that we produce flow graphs in Static Single Information (SSI, \cite{SSI}) -form, an extension of Static Single Assignment (\cite{SSA}): each variable is +Note that we produce flow graphs in Static Single Information or SSI\cite{SSI} +form, an extension of Static Single Assignment\cite{SSA}: each variable is only used in exactly one basic block. All variables that are not dead at the end of a basic block are explicitly carried over to the next block and renamed. While the Flow Object Space is quite a short piece of code -- its core -functionality holds in 300 lines -- the detail of the interactions -sketched above is not entierely straightforward; we refer the reader to +functionality takes only 300 lines -- the detail of the interactions +sketched above is not entirely straightforward; we refer the reader to \cite{D} for more information. @@ -597,7 +597,7 @@ Additionally, for a particular ``entry point'' function, the annotator is provided with user-specified types for the function's arguments. -The goal of the annotator is to find the most precise type that can be +The goal of the annotator is to find the most precise of our types that can be given to each variable of all control flow graphs while respecting the constraints imposed by the operations in which these variables are involved. @@ -640,14 +640,14 @@ We can consider that all variables are initially assigned the ``bottom'' type corresponding to the empty set of possible run-time values. Types can only ever be generalised, and the model is simple enough to show -that there is no infinite chain of generalisation, so that this process +that there is no infinite chain of generalization, so that this process necessarily terminates. \subsection{RPython types} As seen in section \ref{systemprog}, we use the annotator with more than one type -systems. The more interesting and complex one is the RPython type +systems. The most interesting and complex one is the RPython type system, which describes how the input RPython program can be annotated. The other type systems contain lower-level, C-like types that are mostly unordered, thus forming more trivial lattices than the one formed by @@ -708,7 +708,7 @@ out a number of other annotations that are irrelevant for the basic description of the annotator and straightforward to handle: $Dictionary$, $Tuple$, $Float$, $UnicodePoint$, $Iterator$, etc. The -complete list is described in document \cite{T}. +complete list is described in \cite{T}. The type system moreover comes with a family of rules, which for every operation and every sensible combination of input types describes the @@ -780,7 +780,7 @@ involve the lattice of Pbcs, involving variables that could contain e.g.\ one function object among many. An example of such behavior is code manipulating a table of function objects: when an item is read -out of the table, its type is a large Pbc set: $Pbc(\{f1, f2, f3, +out of the table, its type is a large Pbc set: $Pbc(\{f_1, f_2, f_3, \ldots\})$. But in this example, the whole set is available at once, and not built incrementally by successive discoveries. This seems to be often the case in practice: it is not very common for programs to @@ -903,12 +903,12 @@ \subsection{Performance} Our tool-chain is capable of translating the Python interpreter of -PyPy, written in RPython, producing right now either ANSI C code as -described before, or LLVM\footnote{The LLVM project is the realisation +PyPy, written in RPython, currently producing either ANSI C code as +described before, or LLVM\footnote{The LLVM project is the realization of a portable assembler infrastructure, offering both a virtual machine with JIT capabilities and static compilation. Currently we are -using the latter with its good high-level optimisations for PyPy.} -assembler which is then natively compiled with LLVM tools. +using the latter with its good high-level optimizations for PyPy.} +assembler which is then compiled to native code with LLVM tools. The tool-chain has been tested with and can sucessfully apply transformations enabling various combinations of features. The @@ -945,21 +945,21 @@ cache. The rows correspond to variants of the translation process, as follows: -{\bf pypy-c.} - The simplest variant: translated to C code with no explicit memory +{\bf pypy-c:} + The simplest variant; translated to C code with no explicit memory management, and linked with the Boehm conservative GC. -{\bf pypy-c-thread.} - The same, with OS thread support enabled. (For measurement purposes, - thread support is kept separate because it has an impact on the GC - performance.) +{\bf pypy-c-thread:} + The same, with OS thread support enabled (thread support is kept + separate for measurement purposes because it has an impact on the + GC performance). -{\bf pypy-c-stackless.} +{\bf pypy-c-stackless:} The same as pypy-c, plus the ``stackless transformation'' step which - modifies the flow graph of all functions in a way that allows them + modifies the flow graph of all functions to allow them to save and restore their local state, as a way to enable coroutines. -{\bf pypy-c-gcframework.} +{\bf pypy-c-gcframework:} In this variant, the ``gc transformation'' step inserts explicit memory management and a simple mark-and-sweep GC implementation. The resulting program is not linked with Boehm. Note that it is not @@ -967,7 +967,7 @@ in this variant each function explicitly pushes and pops all roots to an alternate stack around each subcall. -{\bf pypy-c-stackless-gcframework.} +{\bf pypy-c-stackless-gcframework:} This variant combines the ``gc transformation'' step with the ``stackless transformation'' step. The overhead introduced by the stackless feature is theoretically balanced with the removal of the @@ -979,13 +979,13 @@ by the extreme size of the executable in this case -- 21MB, compared to 6MB for the basic pypy-c. Making it smaller is work in progress.) -{\bf pypy-llvm-c.} +{\bf pypy-llvm-c:} The same as pypy-c, but using the LLVM back-end instead of the C back-end. The LLVM assembler-compiler gives the best results when - as we do here -- it optimizes its input and generates again C code, which is fed to GCC. -{\bf pypy-llvm-c-prof.} +{\bf pypy-llvm-c-prof:} The same as pypy-llvm-c, but using GCC's profile-driven optimizations. @@ -998,7 +998,7 @@ Boehm GC is known to be less efficient than more customized approach; kernel-level profiling shows that pypy-c typically spends 30\% of its time in the Boehm library. Our current, naively simple mark-and-sweep -GC is even quite worse. The interaction with processor caches is also +GC is manages to be a bit worse. The interaction with processor caches is also hard to predict and account for; in general, we tend to produce relatively large amounts of code and prebuilt data. @@ -1075,10 +1075,10 @@ To achieve high performance for dynamic languages such as Python, the proven approach is to use dynamic compilation techniques, i.e.\ to write JITs. With direct techniques, this is however a major endeavour, and -increases the efforts to further evolve the language. +increases the effort involved in further evolution of the language. In the context of the PyPy project, we are now exploring -- as we planned -from the start -- the possibility to produce a JIT as a graph +from the start -- the possibility of producing a JIT as a graph transformation aspect from the Python interpreter. This idea is based on the theoretical possibiliy to turn interpreters into compilers by partial evaluation\cite{Jones:1993:PartialEvaluation}. @@ -1088,7 +1088,7 @@ binding-time analysis on these graphs, again with abstract interpretation techniques reusing the type inference engine. The next step is to transform the graphs -- following the binding-time annotations -- into a compiler; more precisely, in partial evalution terminology, a +-- into a compiler; more precisely, in partial evalution terminology, a generating extension. We can currently do this on trivial examples. The resulting generating extension will be essentially similar to @@ -1147,7 +1147,7 @@ Jikes RVM's native JIT compilers \cite{Jikes-JIT} are not meant to be retargetted to run in other environments -that hardware processors, for example in a CLR/.NET +than hardware processors, for example in a CLR/.NET runtime. Also Jikes RVM pays the complexity of writing a JIT up-front, which also means that features and semantics of the language are encoded in the JIT compiler code. Major changes of the @@ -1177,7 +1177,7 @@ progress, but given that many of the initial components are shared with the existing stack of transformations leading to C, we are confident that this work will soon give results. Moreover, we believe that these -results will show a reasonable efficiency, because the back-ends for VMs +results will show reasonable efficiency, because the back-ends for VMs like Squeak and .NET can take advantage of high-level input (as opposed to trying to translate, say, C-like code to Smalltalk). From hpk at codespeak.net Wed May 31 18:53:56 2006 From: hpk at codespeak.net (hpk at codespeak.net) Date: Wed, 31 May 2006 18:53:56 +0200 (CEST) Subject: [pypy-svn] r28021 - pypy/extradoc/talk/ep2006 Message-ID: <20060531165356.6667F1005A@code0.codespeak.net> Author: hpk Date: Wed May 31 18:48:27 2006 New Revision: 28021 Modified: pypy/extradoc/talk/ep2006/archsession.txt Log: final tweaks before submission Modified: pypy/extradoc/talk/ep2006/archsession.txt ============================================================================== --- pypy/extradoc/talk/ep2006/archsession.txt (original) +++ pypy/extradoc/talk/ep2006/archsession.txt Wed May 31 18:48:27 2006 @@ -22,18 +22,17 @@ In this session we will present and interactively discuss with the audience the basic architectural pictures of PyPy - a next -generation Python compiler and interpreter. We'd are going to -emphasize the various emerging possibilities for further -development part of which will be an ongoing effort of the -European Union's funded part of the PyPy project. We also +generation Python compiler and interpreter. We will emphasize +emphasize various emerging possibilities enabled by our +architecture and ask the audience for questions. In particular, we'll describe the following architectural pictures and point out extension and optimization possibilities: - Language Implementation: Bytecode Interpreter and Object Space interaction -- Translation to low level languages (C/LLVM) -- Translation to higher level languages (e.g. Squeak/Java/.NET) -- JIT-compiler architecture (very-low-level/l3 interpreter) +- Translation to low level languages (e.g. C/LLVM) +- Translation to higher level languages (e.g. .NET/Squeak) +- JIT-compiler architecture - Interweaving of Garbage Collection, threading and stackless operations into the translation process From mwh at codespeak.net Wed May 31 18:56:37 2006 From: mwh at codespeak.net (mwh at codespeak.net) Date: Wed, 31 May 2006 18:56:37 +0200 (CEST) Subject: [pypy-svn] r28022 - pypy/extradoc/talk/dls2006 Message-ID: <20060531165637.55B1A1005A@code0.codespeak.net> Author: mwh Date: Wed May 31 18:56:35 2006 New Revision: 28022 Modified: pypy/extradoc/talk/dls2006/paper.tex Log: two small tweaks motivated by line lengths. Modified: pypy/extradoc/talk/dls2006/paper.tex ============================================================================== --- pypy/extradoc/talk/dls2006/paper.tex (original) +++ pypy/extradoc/talk/dls2006/paper.tex Wed May 31 18:56:35 2006 @@ -815,13 +815,13 @@ \end{verbatim} % Although the type of \texttt{x} may be some parent class of -\texttt{MyClass}, it can be deduced to be of the more precise type -$Inst(MyClass)$ within the positive branch of the -\texttt{if}.\footnote{Remember that our graphs are in SSI form, -which means that the -\texttt{x} inside each basic block is a different Variable with a -possibly different type as annotation. Given that our type inference -is not flow-sensitive, SSI gives an advantage over SSA here.} +\texttt{MyClass}, within the positive branch of the \texttt{if} it can +be deduced to be of the more precise type $Inst(MyClass)$.\footnote{Remember + that our graphs are in SSI form, which means +that the \texttt{x} inside each basic block is a different Variable +with a possibly different type as annotation. Given that our type +inference is not flow-sensitive, SSI gives an advantage over SSA +here.} This is implemented by introducing an extended family of types for boolean values: @@ -1061,7 +1061,7 @@ the compiled Python interpreters is still not up to competing with the well-established CPython. We are always working to improve matters, considering new optimizations and better GCs. Also, the OOTyper and -back-ends for Smalltalk/Squeak and CLI/.NET are currently in progress. +back-ends for CLI/.NET and Smalltalk/Squeak are currently in progress. \subsection{JIT Specializer} From arigo at codespeak.net Wed May 31 18:58:21 2006 From: arigo at codespeak.net (arigo at codespeak.net) Date: Wed, 31 May 2006 18:58:21 +0200 (CEST) Subject: [pypy-svn] r28023 - in pypy/extradoc/talk/dls2006: . image Message-ID: <20060531165821.A497B10068@code0.codespeak.net> Author: arigo Date: Wed May 31 18:58:19 2006 New Revision: 28023 Added: pypy/extradoc/talk/dls2006/image/arch.dot pypy/extradoc/talk/dls2006/image/arch.pdf (contents, props changed) Modified: pypy/extradoc/talk/dls2006/draft.txt pypy/extradoc/talk/dls2006/paper.tex Log: Some kind of translation overview graph. Modified: pypy/extradoc/talk/dls2006/draft.txt ============================================================================== --- pypy/extradoc/talk/dls2006/draft.txt (original) +++ pypy/extradoc/talk/dls2006/draft.txt Wed May 31 18:58:19 2006 @@ -143,11 +143,7 @@ calls, and thus only gradually discovers (the reachable parts of) the input program. -:: - - [figure 0: flow graph and annotator, e.g. part of doc/image/translation.* - then a stack of transformations - ] +.. graphviz:: image/arch.dot 1. We take as input RPython functions [#]_, and convert them to control flow graphs - a structure amenable to analysis. These flow graphs contain Added: pypy/extradoc/talk/dls2006/image/arch.dot ============================================================================== --- (empty file) +++ pypy/extradoc/talk/dls2006/image/arch.dot Wed May 31 18:58:19 2006 @@ -0,0 +1,21 @@ +digraph arch { + rankdir=LR + input [label="input RPython program", color=white]; + cpy [label="CPython Interpreter", shape=record]; + funcs [label="function objects", color=white]; + frontend [label="Flow Graphing|Type Inference", shape=record]; + graphs [label="forest of typed flow graphs", color=white]; + stack [label="Transformation 1|Transformation 2|Transformation 3| Back-end", shape=record]; + end [label="compiled code", color=white]; + + subgraph { rank=same input cpy } + subgraph { rank=same funcs frontend } + subgraph { rank=same graphs stack } + + input -> cpy [arrowhead=vee, arrowsize=0.75]; + cpy -> funcs; + funcs -> frontend [arrowhead=vee, arrowsize=0.75]; + graphs -> frontend [dir=back]; + graphs -> stack [arrowhead=vee, arrowsize=0.75]; + stack:be -> end; +} Added: pypy/extradoc/talk/dls2006/image/arch.pdf ============================================================================== Binary file. No diff available. Modified: pypy/extradoc/talk/dls2006/paper.tex ============================================================================== --- pypy/extradoc/talk/dls2006/paper.tex (original) +++ pypy/extradoc/talk/dls2006/paper.tex Wed May 31 18:58:19 2006 @@ -134,28 +134,22 @@ \label{translationprocess} The translation process starts from RPython source code and eventually -produces low-level code suitable for the target environment. It can be -described as performing a series of step-wise transformations. Each -step is based on control flow graph transformations and rewriting, and -on the ability to augment the program with further implementation code -written in Python and analysed with the suitable type system. +produces low-level code suitable for the target environment. Its +architecture is shown in figure \ref{fig_arch}. It can be described as +a front-end followed by a series of step-wise transformations. Each +transformation step is based on control flow graph transformations and +rewriting, and on the ability to augment the program with further +implementation code written in Python and analysed with the suitable +type system. The front-end part of the translation process analyses the input RPython program in two phases, as follows:\footnote{Note that the two phases are intermingled in time, because type inference proceeds from an entry point function and follows all calls, and thus only gradually discovers (the reachable parts of) the input program.} - -\begin{verbatim} -:: - - [figure 0: flow graph and annotator, e.g. part of doc/image/translation.* - then a stack of transformations - ] -\end{verbatim} % \begin{enumerate} -\item We take as input RPython functions,\footnote{The input to our +\item We take as input RPython function objects,\footnote{The input to our translation chain are indeed loaded runtime function objects, not source code or ASTs. This enables a form of staged programming in which we can use unrestricted @@ -190,6 +184,14 @@ ready to be compiled. +\begin{figure} +\centering +\includegraphics[scale=0.667]{image/arch.pdf} +\caption{Overview of the translation process.} +\label{fig_arch} +\end{figure} + + \subsection{Transformations} When the translation target is C or C-like environments, the first of From arigo at codespeak.net Wed May 31 19:57:36 2006 From: arigo at codespeak.net (arigo at codespeak.net) Date: Wed, 31 May 2006 19:57:36 +0200 (CEST) Subject: [pypy-svn] r28027 - in pypy/extradoc/talk/dls2006: . image Message-ID: <20060531175736.8A5EA10036@code0.codespeak.net> Author: arigo Date: Wed May 31 19:57:34 2006 New Revision: 28027 Added: pypy/extradoc/talk/dls2006/image/screenshot-bw.pdf pypy/extradoc/talk/dls2006/image/screenshot.png (contents, props changed) Modified: pypy/extradoc/talk/dls2006/paper.bib pypy/extradoc/talk/dls2006/paper.tex Log: Added the screenshot. Moved the figures around until they are reasonably placed. Added: pypy/extradoc/talk/dls2006/image/screenshot-bw.pdf ============================================================================== Files (empty file) and pypy/extradoc/talk/dls2006/image/screenshot-bw.pdf Wed May 31 19:57:34 2006 differ Added: pypy/extradoc/talk/dls2006/image/screenshot.png ============================================================================== Binary file. No diff available. Modified: pypy/extradoc/talk/dls2006/paper.bib ============================================================================== --- pypy/extradoc/talk/dls2006/paper.bib (original) +++ pypy/extradoc/talk/dls2006/paper.bib Wed May 31 19:57:34 2006 @@ -1,7 +1,6 @@ -% fix @inproceedings{PlugType, author = {Bracha, Gilad }, - journal = {Workshop on Revival of Dynamic Languages}, + booktitle = {OOPSLA04 Workshop on Revival of Dynamic Languages}, keywords = {language-implementation}, month = {October}, priority = {2}, @@ -146,7 +145,7 @@ } % constraint-based type inference - at inproceedings{679874, + at inproceedings{Constraint, author = {Tiejun Wang and Scott F. Smith}, title = {Precise Constraint-Based Type Inference for Java}, booktitle = {ECOOP '01: Proceedings of the 15th European Conference on Object-Oriented Programming}, @@ -210,7 +209,7 @@ @misc{boehm-softw, author = "Hans Boehm", -title = "A garbage collector for C and C++", +title = "A garbage collector for {C} and {C++}", url = "http://www.hpl.hp.com/personal/Hans_Boehm/gc/", note = "http://www.hpl.hp.com/personal/Hans\_Boehm/gc/" } @@ -246,7 +245,7 @@ @misc{cpy243, author = "Guido van Rossum et al.", - title="{CPython} 1.4.3", + title="{CPython} 2.4.3", note = "http://www.python.org/download/releases/2.4.3/", url = "http://www.python.org/download/releases/2.4.3/", year = 2006, Modified: pypy/extradoc/talk/dls2006/paper.tex ============================================================================== --- pypy/extradoc/talk/dls2006/paper.tex (original) +++ pypy/extradoc/talk/dls2006/paper.tex Wed May 31 19:57:34 2006 @@ -187,7 +187,7 @@ \begin{figure} \centering \includegraphics[scale=0.667]{image/arch.pdf} -\caption{Overview of the translation process.} +\caption{overview of the translation process.} \label{fig_arch} \end{figure} @@ -303,7 +303,7 @@ itemsarray = lst.items # get the 'items' field itemsarray[index] = item # behaves like a C array \end{verbatim} -\caption{A helper to implement \texttt{list.append()}.} +\caption{a helper to implement \texttt{list.append()}.} \label{fig_llappend} \end{figure} @@ -331,7 +331,8 @@ operations at RPython level is, comparatively speaking, quite large: all list and dictionary operations, instance and class attribute accesses, many string processing methods, a good subset of all Python -built-in functions... Compared to other approaches [e.g.\ Squeak], we +built-in functions... Compared to other approaches +(e.g.\ Squeak \cite{Squeak}), we do not try to minimize the number of primitives -- at least not at the source level. It is fine to have many primitives at any high enough level, because they can all be implemented at the next lower level in @@ -418,9 +419,9 @@ The various analyses used -- from type inference to lifetime analysis - -are generally formulated as [abstract interpretation]. While this +are generally formulated as \textit{abstract interpretation.} While this approach is known to be less efficient than more tailored algorithms -like constraint-based type inference, we gain in freedom, +like constraint-based type inference \cite{Constraint}, we gain in freedom, controllability and simplicity. This proved essential in our overall approach: as described in section \ref{systemprog}, we need to perform type inference with many different type systems, the details of which @@ -464,17 +465,19 @@ objects, and then handles and transforms these graphs. We found in-process debugging sufficient and did not implement dumping -of any intermediate step to disk. Figure 3 shows the control flow graph +of any intermediate step to disk. Figure \ref{fig_screenshot} +shows the control flow graph obtained for a simple function -- this is a screenshot from our graph viewer, used for debugging; basic block placement is performed by Graphviz \cite{graphviz}. -\begin{verbatim} -:: +\begin{figure} +\includegraphics[scale=0.59]{image/screenshot-bw.pdf} +\caption{the control flow graph of a simple function, computed and +displayed by our tool-chain.} +\label{fig_screenshot} +\end{figure} - [figure 3: insert a nice pygame screenshot] -\end{verbatim} - The actual transformation from function objects -- i.e.\ bytecode -- to flow graph is performed by the Flow Object Space, a short but generic plug-in component for the Python interpreter of PyPy. The architecture @@ -482,13 +485,13 @@ \begin{figure} \centering - \caption{the interpreter and object spaces} \label{interpobjspace} \begin{tabular}{|c|c|} \hline -\multicolumn{2}{|c|}{forest of bytecode objects from the application} \\ \hline -\multicolumn{2}{|c|}{Python bytecode interpreter} \\ \hline - Standard Object Space & Flow Object Space \\ \hline +\multicolumn{2}{|c|}{\vphantom{\Large X}forest of bytecode objects from the application} \\ \hline +\multicolumn{2}{|c|}{\vphantom{\Large X}Python bytecode interpreter} \\ \hline + \vphantom{\Large X} Standard Object Space & Flow Object Space \\ \hline \end{tabular} + \caption{the interpreter and object spaces.} \end{figure} Note that the left column, i.e.\ the bytecode interpreter and the @@ -515,7 +518,7 @@ \begin{figure*} \centering \includegraphics[scale=0.75]{image/flowlattice.pdf} -\caption{The lattice order of the flow object space} +\caption{the lattice order of the flow object space.} \label{flowlattice} \end{figure*} @@ -582,6 +585,13 @@ \subsection{The Annotator} +\begin{figure*} +\centering +\includegraphics[scale=0.667]{image/lattice1.pdf} +\caption{the overall lattice.} +\label{latticeoverall} +\end{figure*} + The type inference engine, which we call the \textit{annotator}, is the central component of the front-end part of the translation process. Given a program considered as a family of control flow graphs, the annotator @@ -688,22 +698,14 @@ types are ordered to form a lattice. We mostly use its structure of join-semilattice only. -\begin{figure*} -\centering -\includegraphics[scale=0.75]{image/lattice1.pdf} -\caption{The overall lattice} -\label{latticeoverall} -\end{figure*} - -\begin{figure*} +\begin{figure} \centering -\includegraphics[scale=0.75]{image/lattice2.pdf} -\caption{The part about instances and nullable instances, assuming a +\includegraphics[scale=0.667]{image/lattice2.pdf} +\caption{the part about instances and nullable instances, assuming a simple class hierarchy with only two direct subclasses of \texttt{object}.} \label{latticedetail} -\end{figure*} - +\end{figure} All list terms for all variables are unordered. The Pbcs form a classical finite set-of-subsets lattice. In addition, we have left @@ -923,7 +925,6 @@ \begin{table*} % the layout of this table isn't wonderful, but it's probably OK. \centering -\caption{Summary of interpreter performance} \label{perfsumm} \begin{tabular}{|l|c|c|} \hline \textbf{Interpreter} & @@ -938,6 +939,7 @@ pypy-llvm-c & 3797ms (4.8x) & 7763 (5.2x) \\ \hline pypy-llvm-c-prof & 2772ms (3.5x) & 10245 (3.9x) \\ \hline \end{tabular} +\caption{summary of interpreter performance.} \end{table*} The numbers in parenthesis are slow-down factors compared to CPython. @@ -1012,7 +1014,6 @@ \begin{table*} \centering -\caption{Dividing overall translation time by stage} \label{translationtimes} \begin{tabular}{|p{0.65\linewidth}|c|} \hline \textbf{Step} & \textbf{Time (minutes:seconds)} \\ \hline @@ -1038,6 +1039,7 @@ Compiling (\texttt{gcc -O2}) & 3:23 \\ \hline \end{tabular} +\caption{dividing overall translation time by stage.} \end{table*} An interesting feature of this table is that type inference is not the From arigo at codespeak.net Wed May 31 20:09:37 2006 From: arigo at codespeak.net (arigo at codespeak.net) Date: Wed, 31 May 2006 20:09:37 +0200 (CEST) Subject: [pypy-svn] r28028 - pypy/extradoc/talk/dls2006 Message-ID: <20060531180937.4039F10060@code0.codespeak.net> Author: arigo Date: Wed May 31 20:09:36 2006 New Revision: 28028 Modified: pypy/extradoc/talk/dls2006/paper.tex Log: Tentative categories. Modified: pypy/extradoc/talk/dls2006/paper.tex ============================================================================== --- pypy/extradoc/talk/dls2006/paper.tex (original) +++ pypy/extradoc/talk/dls2006/paper.tex Wed May 31 20:09:36 2006 @@ -23,6 +23,11 @@ \date{31 May 2006} \maketitle +\category{D.3.4}{Programming Languages}{Processors}[code generation, +interpreters, run-time environments] +\category{F.3.2}{Logics and Meanings of Programs}{Semantics of Programming +Languages}[program analysis] + \begin{abstract} The PyPy project seeks to prove both on a research and a practical level the feasibility of writing a virtual machine (VM) @@ -298,10 +303,10 @@ \begin{verbatim} def ll_append(lst, newitem): # Append an item to the end of the vector. - index = lst.length # get the 'length' field - ll_resize(lst, index+1) # call another helper - itemsarray = lst.items # get the 'items' field - itemsarray[index] = item # behaves like a C array + index = lst.length #get the 'length' field + ll_resize(lst, index+1) #call another helper + itemsarray = lst.items #get the 'items' field + itemsarray[index] = item #behaves like a C array \end{verbatim} \caption{a helper to implement \texttt{list.append()}.} \label{fig_llappend} From arigo at codespeak.net Wed May 31 20:17:08 2006 From: arigo at codespeak.net (arigo at codespeak.net) Date: Wed, 31 May 2006 20:17:08 +0200 (CEST) Subject: [pypy-svn] r28029 - pypy/extradoc/talk/dls2006 Message-ID: <20060531181708.20E2D10060@code0.codespeak.net> Author: arigo Date: Wed May 31 20:17:07 2006 New Revision: 28029 Modified: pypy/extradoc/talk/dls2006/paper.bib Log: Urls too long. Split manually. Modified: pypy/extradoc/talk/dls2006/paper.bib ============================================================================== --- pypy/extradoc/talk/dls2006/paper.bib (original) +++ pypy/extradoc/talk/dls2006/paper.bib Wed May 31 20:17:07 2006 @@ -180,15 +180,15 @@ title = {PyPy - Translation}, author = "{PyPy Team}", url = {http://codespeak.net/pypy/dist/pypy/doc/translation.html}, -note = {http://codespeak.net/pypy/dist/pypy/doc/translation.html}, +note = {http://codespeak.net/pypy/dist/pypy/doc/trans-lation.html}, howpublished = {Web page, in-progress.} } @misc{A, title = {PyPy - Architecture Overview}, author = "{PyPy Team}", -note = {http://codespeak.net/pypy/dist/pypy/doc/architecture.html}, url = "http://codespeak.net/pypy/dist/pypy/doc/architecture.html", +note = {http://codespeak.net/pypy/dist/pypy/doc/archi-tecture.html}, howpublished = {Web page} } From arigo at codespeak.net Wed May 31 20:23:47 2006 From: arigo at codespeak.net (arigo at codespeak.net) Date: Wed, 31 May 2006 20:23:47 +0200 (CEST) Subject: [pypy-svn] r28030 - pypy/extradoc/talk/dls2006 Message-ID: <20060531182347.1919C10060@code0.codespeak.net> Author: arigo Date: Wed May 31 20:23:46 2006 New Revision: 28030 Modified: pypy/extradoc/talk/dls2006/paper.bib Log: Add the final \balancecolumns. Yes, it's in the bib file. Yes, it's in the middle of the authors of a random entry. Yes, it's hack. Modified: pypy/extradoc/talk/dls2006/paper.bib ============================================================================== --- pypy/extradoc/talk/dls2006/paper.bib (original) +++ pypy/extradoc/talk/dls2006/paper.bib Wed May 31 20:23:46 2006 @@ -55,7 +55,9 @@ % Squeak/ PreScheme @inproceedings{Squeak, - author = {Dan Ingalls and Ted Kaehler and John Maloney and Scott Wallace and Alan Kay}, + author = {Dan Ingalls and Ted Kaehler and John Maloney and Scott Wallace and +\balancecolumns + Alan Kay}, title = {Back to the future: the story of Squeak, a practical Smalltalk written in itself}, booktitle = {OOPSLA '97: Proceedings of the 12th ACM SIGPLAN conference on Object-oriented programming, systems, languages, and applications}, year = {1997}, From cfbolz at codespeak.net Wed May 31 20:29:20 2006 From: cfbolz at codespeak.net (cfbolz at codespeak.net) Date: Wed, 31 May 2006 20:29:20 +0200 (CEST) Subject: [pypy-svn] r28031 - pypy/extradoc/talk/ep2006 Message-ID: <20060531182920.E2C6010063@code0.codespeak.net> Author: cfbolz Date: Wed May 31 20:29:18 2006 New Revision: 28031 Modified: pypy/extradoc/talk/ep2006/abstract_methodtalk.txt Log: fix underline :-) Modified: pypy/extradoc/talk/ep2006/abstract_methodtalk.txt ============================================================================== --- pypy/extradoc/talk/ep2006/abstract_methodtalk.txt (original) +++ pypy/extradoc/talk/ep2006/abstract_methodtalk.txt Wed May 31 20:29:18 2006 @@ -2,7 +2,7 @@ -------------------------------------------- Kill -1: process refactoring in the PyPy project -============================= +================================================= In this talk we will present the experiences of running a collaborative OSS project within a EU-funded consortium structure. We will briefly present @@ -13,4 +13,4 @@ implemented. We will spice up the analysis of the main drivers behind this change by refererring to Hershey-Blanchards Situational Leadership model. -Author: Beatrice D?ring \ No newline at end of file +Author: Beatrice D?ring From cfbolz at codespeak.net Wed May 31 20:29:38 2006 From: cfbolz at codespeak.net (cfbolz at codespeak.net) Date: Wed, 31 May 2006 20:29:38 +0200 (CEST) Subject: [pypy-svn] r28032 - pypy/extradoc/talk/ep2006 Message-ID: <20060531182938.1AFD11005A@code0.codespeak.net> Author: cfbolz Date: Wed May 31 20:29:35 2006 New Revision: 28032 Added: pypy/extradoc/talk/ep2006/usecases.txt Log: first draft at "what can pypy do for you" talk Added: pypy/extradoc/talk/ep2006/usecases.txt ============================================================================== --- (empty file) +++ pypy/extradoc/talk/ep2006/usecases.txt Wed May 31 20:29:35 2006 @@ -0,0 +1,33 @@ +What can PyPy do for you? +========================= + +Armin Rigo, Eric van Riet Paap, Carl Friedrich Bolz + +Contact Information +------------------- + +pypy-dev at codespeak.net (developer mailing list) +arigo at tunes.org +eric at vanrietpaap.nl +cfbolz at gmx.de + +Requested Timeslot +------------------ + +30 minutes (or longer). + +Abstract +-------- + +This talk describes some of the novel features of the PyPy project (a next +generation Python interpreter) which are made possible by PyPy's flexible +architecture. The talk focuses mostly on the features and examples about how +they can be used and less about their implementation. Specifically we will +discuss and showcase the following: + + - lazy evaluation with the thunk object space + - lightweight threadlets similar to what stackless python provides + - Oz-like dataflow variables with the logic object space (XXX do we really want that?) + - Writing compatible extension modules for PyPy and CPython with the PyPy + extension compiler + - The Javascript backend From cfbolz at codespeak.net Wed May 31 21:37:00 2006 From: cfbolz at codespeak.net (cfbolz at codespeak.net) Date: Wed, 31 May 2006 21:37:00 +0200 (CEST) Subject: [pypy-svn] r28035 - pypy/extradoc/talk/ep2006 Message-ID: <20060531193700.D018610063@code0.codespeak.net> Author: cfbolz Date: Wed May 31 21:36:58 2006 New Revision: 28035 Modified: pypy/extradoc/talk/ep2006/usecases.txt Log: some small tweaks Modified: pypy/extradoc/talk/ep2006/usecases.txt ============================================================================== --- pypy/extradoc/talk/ep2006/usecases.txt (original) +++ pypy/extradoc/talk/ep2006/usecases.txt Wed May 31 21:36:58 2006 @@ -27,7 +27,7 @@ - lazy evaluation with the thunk object space - lightweight threadlets similar to what stackless python provides - - Oz-like dataflow variables with the logic object space (XXX do we really want that?) + - Oz-like dataflow variables with the logic object space - Writing compatible extension modules for PyPy and CPython with the PyPy extension compiler - - The Javascript backend + - The Javascript backend and its uses From hpk at codespeak.net Wed May 31 21:40:55 2006 From: hpk at codespeak.net (hpk at codespeak.net) Date: Wed, 31 May 2006 21:40:55 +0200 (CEST) Subject: [pypy-svn] r28036 - pypy/extradoc/talk/ep2006 Message-ID: <20060531194055.496E110060@code0.codespeak.net> Author: hpk Date: Wed May 31 21:40:53 2006 New Revision: 28036 Modified: pypy/extradoc/talk/ep2006/usecases.txt Log: de-verbosing the usecases description a bit i am slightly doubtful if you can really showcase all the listed features in 30 minutes. Rather, i guess you should select two to show and just describe the others in slides or see that you get a 1h slot (three talkers after all). Modified: pypy/extradoc/talk/ep2006/usecases.txt ============================================================================== --- pypy/extradoc/talk/ep2006/usecases.txt (original) +++ pypy/extradoc/talk/ep2006/usecases.txt Wed May 31 21:40:53 2006 @@ -19,11 +19,11 @@ Abstract -------- -This talk describes some of the novel features of the PyPy project (a next -generation Python interpreter) which are made possible by PyPy's flexible -architecture. The talk focuses mostly on the features and examples about how -they can be used and less about their implementation. Specifically we will -discuss and showcase the following: +This talk describes novel features of the PyPy project (a next +generation Python interpreter) which are made possible by +its flexible architecture. The talk focuses mostly on example +usages and less about their implementation. Specifically we +will discuss and showcase the following: - lazy evaluation with the thunk object space - lightweight threadlets similar to what stackless python provides